diff --git a/enaml/qt/qt_window.py b/enaml/qt/qt_window.py index 47f3abf6f..d50f8a501 100644 --- a/enaml/qt/qt_window.py +++ b/enaml/qt/qt_window.py @@ -7,10 +7,11 @@ #------------------------------------------------------------------------------ from atom.api import Typed +from enaml.layout.geometry import Pos, Rect, Size from enaml.widgets.window import ProxyWindow -from .QtCore import Qt, QSize, Signal -from .QtGui import QFrame, QLayout, QIcon +from .QtCore import Qt, QPoint, QRect, QSize, Signal +from .QtGui import QApplication, QFrame, QLayout, QIcon from .q_resource_helpers import get_cached_qicon from .q_single_widget_layout import QSingleWidgetLayout @@ -215,7 +216,9 @@ def init_widget(self): if d.title: self.set_title(d.title) if -1 not in d.initial_size: - self.set_initial_size(d.initial_size) + self.widget.resize(*d.initial_size) + if -1 not in d.initial_position: + self.widget.move(*d.initial_position) if d.modality != 'non_modal': self.set_modality(d.modality) if d.icon: @@ -276,11 +279,77 @@ def child_removed(self, child): #-------------------------------------------------------------------------- # ProxyWindow API #-------------------------------------------------------------------------- - def close(self): - """ Close the window + def set_title(self, title): + """ Set the title of the window. """ - self.widget.close() + self.widget.setWindowTitle(title) + + def set_modality(self, modality): + """ Set the modality of the window. + + """ + self.widget.setWindowModality(MODALITY[modality]) + + def set_icon(self, icon): + """ Set the window icon. + + """ + if icon: + qicon = get_cached_qicon(icon) + else: + qicon = QIcon() + self.widget.setWindowIcon(qicon) + + def position(self): + """ Get the position of the of the window. + + """ + point = self.widget.pos() + return Pos(point.x(), point.y()) + + def set_position(self, pos): + """ Set the position of the window. + + """ + self.widget.move(*pos) + + def size(self): + """ Get the size of the window. + + """ + size = self.widget.size() + return Size(size.width(), size.height()) + + def set_size(self, size): + """ Set the size of the window. + + """ + size = QSize(*size) + if size.isValid(): + self.widget.resize(size) + + def geometry(self): + """ Get the geometry of the window. + + """ + rect = self.widget.geometry() + return Rect(rect.x(), rect.y(), rect.width(), rect.height()) + + def set_geometry(self, rect): + """ Set the geometry of the window. + + """ + rect = QRect(*rect) + if rect.isValid(): + self.widget.setGeometry(rect) + + def frame_geometry(self): + """ Get the geometry of the window. + + """ + rect = self.widget.frameGeometry() + return Rect(rect.x(), rect.y(), rect.width(), rect.height()) def maximize(self): """ Maximize the window. @@ -312,32 +381,32 @@ def send_to_back(self): """ self.widget.lower() - def set_icon(self, icon): - """ Set the window icon. - - """ - if icon: - qicon = get_cached_qicon(icon) - else: - qicon = QIcon() - self.widget.setWindowIcon(qicon) - - def set_title(self, title): - """ Set the title of the window. + def center_on_screen(self): + """ Center the window on the screen. """ - self.widget.setWindowTitle(title) + widget = self.widget + rect = QRect(QPoint(0, 0), widget.frameGeometry().size()) + geo = QApplication.desktop().screenGeometry(widget) + widget.move(geo.center() - rect.center()) - def set_initial_size(self, size): - """ Set the initial size of the window. + def center_on_widget(self, other): + """ Center the window on another widget. """ - if -1 in size: - return - self.widget.resize(QSize(*size)) + widget = self.widget + rect = QRect(QPoint(0, 0), widget.frameGeometry().size()) + other_widget = other.proxy.widget + if other_widget.isWindow(): + geo = other_widget.frameGeometry() + else: + size = other_widget.size() + point = other_widget.mapToGlobal(QPoint(0, 0)) + geo = QRect(point, size) + widget.move(geo.center() - rect.center()) - def set_modality(self, modality): - """ Set the modality of the window. + def close(self): + """ Close the window. """ - self.widget.setWindowModality(MODALITY[modality]) + self.widget.close() diff --git a/enaml/widgets/window.py b/enaml/widgets/window.py index 4b71ca9c9..88611872a 100644 --- a/enaml/widgets/window.py +++ b/enaml/widgets/window.py @@ -13,7 +13,7 @@ from enaml.application import deferred_call from enaml.core.declarative import d_ from enaml.icon import Icon -from enaml.layout.geometry import Size +from enaml.layout.geometry import Pos, Rect, Size from .container import Container from .widget import Widget, ProxyWidget @@ -35,7 +35,25 @@ def set_modality(self, modality): def set_icon(self, icon): raise NotImplementedError - def close(self): + def position(self): + raise NotImplementedError + + def set_position(self, pos): + raise NotImplementedError + + def size(self): + raise NotImplementedError + + def set_size(self, size): + raise NotImplementedError + + def geometry(self): + raise NotImplementedError + + def set_geometry(self, rect): + raise NotImplementedError + + def frame_geometry(self): raise NotImplementedError def minimize(self): @@ -53,6 +71,15 @@ def send_to_front(self): def send_to_back(self): raise NotImplementedError + def center_on_screen(self): + raise NotImplementedError + + def center_on_widget(self, other): + raise NotImplementedError + + def close(self): + raise NotImplementedError + class Window(Widget): """ A top-level Window component. @@ -75,8 +102,12 @@ class Window(Widget): #: The titlebar text. title = d_(Unicode()) - #: The initial size of the window. A value of (-1, -1) indicates - #: to let the toolkit choose the initial size. + #: The initial position of the window frame. A value of (-1, -1) + #: indicates that the toolkit should choose the initial position. + initial_position = d_(Coerced(Pos, (-1, -1))) + + #: The initial size of the window client area. A value of (-1, -1) + #: indicates that the toolkit should choose the initial size. initial_size = d_(Coerced(Size, (-1, -1))) #: An enum which indicates the modality of the window. The default @@ -134,12 +165,93 @@ def central_widget(self): if isinstance(child, Container): return child - def close(self): - """ Send the 'close' action to the client widget. + def position(self): + """ Get the position of the window frame. + + Returns + ------- + result : Pos + The current position of the window frame. """ if self.proxy_is_active: - self.proxy.close() + return self.proxy.position() + return Pos(-1, -1) + + def set_position(self, pos): + """ Set the position of the window frame. + + Parameters + ---------- + pos : Pos + The desired position of the window the window frame. + + """ + if self.proxy_is_active: + self.proxy.set_position(pos) + + def size(self): + """ Get the size of the window client area. + + Returns + ------- + result : Size + The current size of the window client area. + + """ + if self.proxy_is_active: + return self.proxy.size() + return Size(-1, -1) + + def set_size(self, size): + """ Set the size of the window client area. + + Parameters + ---------- + size : Size + The desired size of the window client area. + + """ + if self.proxy_is_active: + self.proxy.set_size(size) + + def geometry(self): + """ Get the geometry of the window client area. + + Returns + ------- + result : Rect + The current geometry of the window client area. + + """ + if self.proxy_is_active: + return self.proxy.geometry() + return Rect(-1, -1, -1, -1) + + def set_geometry(self, rect): + """ Set the geometry of the window client area. + + Parameters + ---------- + rect : Rect + The desired geometry of the window client area. + + """ + if self.proxy_is_active: + self.proxy.set_geometry(rect) + + def frame_geometry(self): + """ Get the geometry of the window frame. + + Returns + ------- + result : Rect + The current geometry of the window frame. + + """ + if self.proxy_is_active: + return self.proxy.frame_geometry() + return Rect(-1, -1, -1, -1) def maximize(self): """ Send the 'maximize' action to the client widget. @@ -176,6 +288,36 @@ def send_to_back(self): if self.proxy_is_active: self.proxy.send_to_back() + def center_on_screen(self): + """ Center the window on the screen. + + """ + if self.proxy_is_active: + self.proxy.center_on_screen() + + def center_on_widget(self, other): + """ Center this window on another widget. + + Parameters + ---------- + other : Widget + The widget onto which to center this window. + + """ + assert isinstance(other, Widget) + if self.proxy_is_active and other.proxy_is_active: + self.proxy.center_on_widget(other) + + def close(self): + """ Close the window. + + This will cause the window to be hidden, the 'closed' event + to be fired, and the window subsequently destroyed. + + """ + if self.proxy_is_active: + self.proxy.close() + def show(self): """ Show the window to the screen. diff --git a/enaml/wx/wx_window.py b/enaml/wx/wx_window.py index d95b0995a..037ff0081 100644 --- a/enaml/wx/wx_window.py +++ b/enaml/wx/wx_window.py @@ -9,6 +9,7 @@ from atom.api import Typed +from enaml.layout.geometry import Pos, Rect, Size from enaml.widgets.window import ProxyWindow from .wx_action import wxAction @@ -138,7 +139,9 @@ def init_widget(self): if d.title: self.set_title(d.title) if -1 not in d.initial_size: - self.set_initial_size(d.initial_size) + self.widget.SetClientSize(wx.Size(*d.initial_size)) + if -1 not in d.initial_position: + self.widget.Move(wx.Point(*d.initial_position)) if d.icon: self.set_icon(d.icon) self.widget.Bind(wx.EVT_CLOSE, self.on_close) @@ -210,11 +213,78 @@ def on_layout_requested(self, event): #-------------------------------------------------------------------------- # ProxyWindow API #-------------------------------------------------------------------------- - def close(self): - """ Close the window + def set_title(self, title): + """ Set the title of the window. """ - self.widget.Close() + self.widget.SetTitle(title) + + def set_modality(self, modality): + """ Set the modality of the window. + + """ + if modality == 'non_modal': + self.widget.MakeModal(False) + else: + self.widget.MakeModal(True) + + def set_icon(self, icon): + """ This is not supported on Wx. + + """ + pass + + def position(self): + """ Get the position of the of the window. + + """ + point = self.widget.GetPosition() + return Pos(point.x, point.y) + + def set_position(self, pos): + """ Set the position of the window. + + """ + self.widget.SetPosition(wx.Point(*pos)) + + def size(self): + """ Get the size of the window. + + """ + size = self.widget.GetClientSize() + return Size(size.GetWidth(), size.GetHeight()) + + def set_size(self, size): + """ Set the size of the window. + + """ + size = wx.Size(*size) + if size.IsFullySpecified(): + self.widget.SetClientSize(size) + + def geometry(self): + """ Get the geometry of the window. + + """ + # Wx has no standard way of taking into account the size of + # the window frame. I'm not spending time on a workaround. + point = self.widget.GetPosition() + size = self.widget.GetClientSize() + return Rect(point.x, point.y, size.GetWidth(), size.GetHeight()) + + def set_geometry(self, rect): + """ Set the geometry of the window. + + """ + self.set_position(rect[:2]) + self.set_size(rect[2:]) + + def frame_geometry(self): + """ Get the geometry of the window. + + """ + r = self.widget.GetRect() + return Rect(r.GetX(), r.GetY(), r.GetWidth(), r.GetHeight()) def maximize(self): """ Maximize the window. @@ -246,32 +316,26 @@ def send_to_back(self): """ self.widget.Lower() - def set_icon(self, icon): - """ This is not supported on Wx. - - """ - pass - - def set_title(self, title): - """ Set the title of the window. + def center_on_screen(self): + """ Center the window on the screen. """ - self.widget.SetTitle(title) + self.widget.CenterOnScreen() - def set_initial_size(self, size): - """ Set the initial size of the window. + def center_on_widget(self, other): + """ Center the window on another widget. """ - self.widget.SetSize(wx.Size(*size)) + widget = self.widget + rect = widget.GetRect() + geo = other.proxy.widget.GetScreenRect() + widget.Move(rect.CenterIn(geo).GetPosition()) - def set_modality(self, modality): - """ Set the modality of the window. + def close(self): + """ Close the window """ - if modality == 'non_modal': - self.widget.MakeModal(False) - else: - self.widget.MakeModal(True) + self.widget.Close() #-------------------------------------------------------------------------- # Overrides