diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index 5ab7b4e8..8b86a837 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -391,6 +391,7 @@ + diff --git a/src/dlangui/dialogs/dialog.d b/src/dlangui/dialogs/dialog.d index 1955abf1..658622fa 100644 --- a/src/dlangui/dialogs/dialog.d +++ b/src/dlangui/dialogs/dialog.d @@ -24,6 +24,8 @@ import dlangui.core.signals; import dlangui.core.stdaction; import dlangui.widgets.layouts; import dlangui.widgets.controls; +import dlangui.widgets.winframe; +import dlangui.widgets.popup; import dlangui.platforms.common.platform; import std.conv; @@ -34,6 +36,8 @@ enum DialogFlag : uint { Modal = 1, /// dialog can be resized Resizable = 2, + /// dialog is show in popup widget inside current window instead of separate window + Popup = 4, } /// slot to pass dialog result @@ -45,6 +49,7 @@ interface DialogResultHandler { class Dialog : VerticalLayout { protected Window _window; protected Window _parentWindow; + protected PopupWidget _popup; protected UIString _caption; protected uint _flags; protected string _icon; @@ -95,6 +100,7 @@ class Dialog : VerticalLayout { protected const(Action) [] _buttonActions; protected ImageTextButton _defaultButton; + protected ImageTextButton _cancelButton; /// create panel with buttons based on list of actions Widget createButtonsPanel(const(Action) [] actions, int defaultActionIndex, int splitBeforeIndex) { _buttonActions = actions; @@ -111,6 +117,8 @@ class Dialog : VerticalLayout { btn.setState(State.Default); _defaultButton = btn; } + if (a.id == StandardAction.Cancel || a.id == StandardAction.No) + _cancelButton = btn; btn.action = a.clone(); res.addChild(btn); } @@ -146,7 +154,10 @@ class Dialog : VerticalLayout { else if (_parentWindow) _parentWindow.dispatchAction(action); } - window.close(); + if (_popup) + _parentWindow.removePopup(_popup); + else + window.close(); } /// shows dialog @@ -160,11 +171,23 @@ class Dialog : VerticalLayout { layoutWidth = FILL_PARENT; layoutHeight = FILL_PARENT; } - _window = Platform.instance.createWindow(_caption, _parentWindow, wflags); - if (_window && _icon) - _window.windowIcon = drawableCache.getImage(_icon); - _window.mainWidget = this; - _window.show(); + if (_flags & DialogFlag.Popup) { + DialogFrame _frame = new DialogFrame(this, _cancelButton !is null); + if (_cancelButton) { + _frame.onCloseButtonClickListener = delegate(Widget w) { + close(_cancelButton.action); + return true; + }; + } + _popup = _parentWindow.showPopup(_frame); + _popup.flags(PopupFlags.Modal); + } else { + _window = Platform.instance.createWindow(_caption, _parentWindow, wflags); + if (_window && _icon) + _window.windowIcon = drawableCache.getImage(_icon); + _window.mainWidget = this; + _window.show(); + } onShow(); } @@ -176,3 +199,14 @@ class Dialog : VerticalLayout { } } +/// frame with caption for dialog +class DialogFrame : WindowFrame { + protected Dialog _dialog; + this(Dialog dialog, bool enableCloseButton) { + super(dialog.id ~ "_frame", enableCloseButton); + _dialog = dialog; + _caption.text = _dialog.windowCaption.value; + bodyWidget = _dialog; + } +} + diff --git a/src/dlangui/dialogs/msgbox.d b/src/dlangui/dialogs/msgbox.d index fe01eded..a6563082 100644 --- a/src/dlangui/dialogs/msgbox.d +++ b/src/dlangui/dialogs/msgbox.d @@ -43,7 +43,7 @@ class MessageBox : Dialog { protected const(Action)[] _actions; protected int _defaultButtonIndex; this(UIString caption, UIString message, Window parentWindow = null, const(Action) [] buttons = [ACTION_OK], int defaultButtonIndex = 0, bool delegate(const Action result) handler = null) { - super(caption, parentWindow, DialogFlag.Modal); + super(caption, parentWindow, DialogFlag.Modal | DialogFlag.Popup); _message = message; _actions = buttons; _defaultButtonIndex = defaultButtonIndex; diff --git a/src/dlangui/widgets/docks.d b/src/dlangui/widgets/docks.d index 547303b3..09922d61 100644 --- a/src/dlangui/widgets/docks.d +++ b/src/dlangui/widgets/docks.d @@ -23,6 +23,7 @@ module dlangui.widgets.docks; import dlangui.widgets.layouts; import dlangui.widgets.controls; +import dlangui.widgets.winframe; /// dock alignment types enum DockAlignment { @@ -272,17 +273,7 @@ class DockHost : WidgetGroupDefaultDrawing { } /// docked window -class DockWindow : VerticalLayout { - - protected Widget _bodyWidget; - @property Widget bodyWidget() { return _bodyWidget; } - @property void bodyWidget(Widget widget) { - _children.replace(widget, _bodyWidget); - _bodyWidget = widget; - _bodyWidget.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); - _bodyWidget.parent = this; - requestLayout(); - } +class DockWindow : WindowFrame { protected DockAlignment _dockAlignment; @@ -295,46 +286,16 @@ class DockWindow : VerticalLayout { return this; } - protected HorizontalLayout _captionLayout; - protected TextWidget _caption; - protected ImageButton _closeButton; - this(string ID) { super(ID); + } + + override protected void init() { + super.init(); _dockAlignment = DockAlignment.Right; // default alignment is right - init(); } - protected bool onCloseButtonClick(Widget source) { - return true; - } - protected void init() { - - styleId = STYLE_DOCK_WINDOW; - - _captionLayout = new HorizontalLayout("DOCK_WINDOW_CAPTION_PANEL"); - _captionLayout.layoutWidth(FILL_PARENT).layoutHeight(WRAP_CONTENT); - _captionLayout.styleId = STYLE_DOCK_WINDOW_CAPTION; - - _caption = new TextWidget("DOCK_WINDOW_CAPTION"); - _caption.styleId = STYLE_DOCK_WINDOW_CAPTION_LABEL; - - _closeButton = new ImageButton("DOCK_WINDOW_CAPTION_CLOSE_BUTTON"); - _closeButton.styleId = STYLE_BUTTON_TRANSPARENT; - _closeButton.drawableId = "close"; - _closeButton.trackHover = true; - _closeButton.onClickListener = &onCloseButtonClick; - - _captionLayout.addChild(_caption); - _captionLayout.addChild(_closeButton); - - _bodyWidget = createBodyWidget(); - _bodyWidget.styleId = STYLE_DOCK_WINDOW_BODY; - - addChild(_captionLayout); - addChild(_bodyWidget); - } - protected Widget createBodyWidget() { - return new Widget("DOCK_WINDOW_BODY"); - } + //protected Widget createBodyWidget() { + // return new Widget("DOCK_WINDOW_BODY"); + //} } diff --git a/src/dlangui/widgets/popup.d b/src/dlangui/widgets/popup.d index 8b93c048..b3b1322c 100644 --- a/src/dlangui/widgets/popup.d +++ b/src/dlangui/widgets/popup.d @@ -50,6 +50,8 @@ struct PopupAnchor { enum PopupFlags : uint { /// close popup when mouse button clicked outside of its bounds CloseOnClickOutside = 1, + /// modal popup - keypresses and mouse events can be routed to this popup only + Modal = 2, } /** interface - slot for onPopupCloseListener */ diff --git a/src/dlangui/widgets/winframe.d b/src/dlangui/widgets/winframe.d new file mode 100644 index 00000000..8b5839ff --- /dev/null +++ b/src/dlangui/widgets/winframe.d @@ -0,0 +1,89 @@ +// Written in the D programming language. + +/** + +This module implements window frame widget. + + +Synopsis: + +---- +import dlangui.widgets.docks; +---- + + +Copyright: Vadim Lopatin, 2015 +License: Boost License 1.0 +Authors: Vadim Lopatin, coolreader.org@gmail.com +*/ +module dlangui.widgets.winframe; + +import dlangui.widgets.layouts; +import dlangui.widgets.controls; + +/// window frame with caption widget +class WindowFrame : VerticalLayout { + + protected Widget _bodyWidget; + @property Widget bodyWidget() { return _bodyWidget; } + @property void bodyWidget(Widget widget) { + _children.replace(widget, _bodyWidget); + _bodyWidget = widget; + _bodyWidget.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); + _bodyWidget.parent = this; + requestLayout(); + } + + protected HorizontalLayout _captionLayout; + protected TextWidget _caption; + protected ImageButton _closeButton; + protected bool _showCloseButton; + + @property TextWidget caption() { return _caption; } + + this(string ID, bool showCloseButton = true) { + super(ID); + _showCloseButton = showCloseButton; + init(); + } + + Signal!OnClickHandler onCloseButtonClickListener; + protected bool onCloseButtonClick(Widget source) { + if (onCloseButtonClickListener.assigned) + onCloseButtonClickListener(source); + return true; + } + + protected void init() { + + styleId = STYLE_DOCK_WINDOW; + + _captionLayout = new HorizontalLayout("DOCK_WINDOW_CAPTION_PANEL"); + _captionLayout.layoutWidth(FILL_PARENT).layoutHeight(WRAP_CONTENT); + _captionLayout.styleId = STYLE_DOCK_WINDOW_CAPTION; + + _caption = new TextWidget("DOCK_WINDOW_CAPTION"); + _caption.styleId = STYLE_DOCK_WINDOW_CAPTION_LABEL; + + _closeButton = new ImageButton("DOCK_WINDOW_CAPTION_CLOSE_BUTTON"); + _closeButton.styleId = STYLE_BUTTON_TRANSPARENT; + _closeButton.drawableId = "close"; + _closeButton.trackHover = true; + _closeButton.onClickListener = &onCloseButtonClick; + if (!_showCloseButton) + _closeButton.visibility = Visibility.Gone; + + _captionLayout.addChild(_caption); + _captionLayout.addChild(_closeButton); + + _bodyWidget = createBodyWidget(); + _bodyWidget.styleId = STYLE_DOCK_WINDOW_BODY; + + addChild(_captionLayout); + addChild(_bodyWidget); + } + + protected Widget createBodyWidget() { + return new Widget("DOCK_WINDOW_BODY"); + } +}