diff --git a/src/dlangui/core/stdaction.d b/src/dlangui/core/stdaction.d index 43b95875..7c166d65 100644 --- a/src/dlangui/core/stdaction.d +++ b/src/dlangui/core/stdaction.d @@ -31,6 +31,7 @@ enum StandardAction : int { Open, Save, DiscardChanges, + OpenUrl, } const Action ACTION_OK = new Action(StandardAction.Ok, "ACTION_OK"c); @@ -44,4 +45,5 @@ const Action ACTION_IGNORE = new Action(StandardAction.Ignore, "ACTION_IGNORE"c) const Action ACTION_OPEN = new Action(StandardAction.Open, "ACTION_OPEN"c); const Action ACTION_SAVE = new Action(StandardAction.Save, "ACTION_SAVE"c); const Action ACTION_DISCARD_CHANGES = new Action(StandardAction.DiscardChanges, "ACTION_DISCARD_CHANGES"c); +const Action ACTION_OPEN_URL = (new Action(StandardAction.OpenUrl)).iconId("applications-internet"); diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index b4b11b62..b38f12f4 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -394,7 +394,7 @@ wstring fromWStringz(const(wchar) * s) { /** widget state flags - bits */ enum State : uint { /// state not specified / normal - Normal = 4, // Normal is Enabled + Normal = 4 | 256, // Normal is Enabled /// pressed (e.g. clicked by mouse) Pressed = 1, /// widget has focus diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index b28b1e3d..b1eea6e7 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -30,6 +30,7 @@ import dlangui.dialogs.msgbox; private import dlangui.graphics.gldrawbuf; private import std.algorithm; private import core.sync.mutex; +private import std.string; // specify debug=DebugMouseEvents for logging mouse handling // specify debug=DebugRedraw for logging drawing and layouts handling @@ -846,6 +847,19 @@ class Platform { i18n.findTranslationsDir(dirs); return this; } + + /// override to support opening url in external browser + bool openURL(string url) { + Log.d("Platform.openURL(", url, ") is called"); + bool res = false; + version(Windows) { + import win32.shellapi; + ShellExecuteA(null, "open", url.toStringz, null, null, 1); + res = true; + } + // TODO: support other platforms + return res; + } } /// get current platform object instance diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d index b34d192c..669e7e05 100644 --- a/src/dlangui/widgets/controls.d +++ b/src/dlangui/widgets/controls.d @@ -3,16 +3,19 @@ /** This module contains simple controls widgets implementation. -TextWidget +TextWidget - static text -ImageWidget +ImageWidget - image -Button +Button - button with only text -ImageButton +ImageButton - button with only image -ScrollBar +ImageTextButton - button with text and image +ScrollBar - scrollbar control + +UrlImageTextButton - URL link button Synopsis: @@ -29,9 +32,11 @@ module dlangui.widgets.controls; import dlangui.widgets.widget; import dlangui.widgets.layouts; +import dlangui.core.stdaction; private import std.algorithm; private import std.conv : to; +private import std.utf : toUTF32; /// vertical spacer to fill empty space in vertical layouts class VSpacer : Widget { @@ -282,6 +287,24 @@ class ImageTextButton : HorizontalLayout { } +/// button - url +class UrlImageTextButton : ImageTextButton { + this(string ID, dstring labelText, string url, string icon = "applications-internet") { + super(ID, icon, labelText); + Action a = ACTION_OPEN_URL.clone(); + a.label = labelText; + a.stringParam = url; + _action = a; + styleId = null; + //_icon.styleId = STYLE_BUTTON_IMAGE; + //_label.styleId = STYLE_BUTTON_LABEL; + //_label.textFlags(TextFlag.Underline); + _label.ownStyle.getOrCreateState(State.Hovered, State.Hovered).textFlags(TextFlag.Underline); + _label.textColor(0x000080); + padding(Rect(3,3,3,3)); + } +} + /// checkbox class CheckBox : ImageTextButton { this(string ID = null, string textResourceId = null) { diff --git a/src/dlangui/widgets/styles.d b/src/dlangui/widgets/styles.d index 07395aa5..cdcde587 100644 --- a/src/dlangui/widgets/styles.d +++ b/src/dlangui/widgets/styles.d @@ -746,6 +746,17 @@ class Style { return child; } + /// find exact existing state style or create new if no matched styles found + Style getOrCreateState(uint stateMask = 0, uint stateValue = 0) { + if (stateValue == State.Normal) + return this; + foreach(item; _substates) { + if ((item._stateMask == stateMask) && (item._stateValue == stateValue)) + return item; + } + return createState(stateMask, stateValue); + } + /// find substyle based on widget state (e.g. focused, pressed, ...) const(Style) forState(uint state) const { if (state == State.Normal) diff --git a/views/res/mdpi/applications-internet.png b/views/res/mdpi/applications-internet.png new file mode 100644 index 00000000..670c0716 Binary files /dev/null and b/views/res/mdpi/applications-internet.png differ diff --git a/views/standard_resources.list b/views/standard_resources.list index 55abed7a..a2163b3a 100644 --- a/views/standard_resources.list +++ b/views/standard_resources.list @@ -23,6 +23,7 @@ res/main_menu_item_background.xml res/main_menu_item_background_hover.9.png res/main_menu_item_background_normal.9.png res/main_menu_item_background_selected.9.png +res/mdpi/applications-internet.png res/mdpi/arrow_right_down_black.png res/mdpi/arrow_right_hollow.png res/mdpi/btn_check_off.png