diff --git a/examples/example1/src/main.d b/examples/example1/src/main.d index b1767650..c12e6b0a 100644 --- a/examples/example1/src/main.d +++ b/examples/example1/src/main.d @@ -292,7 +292,7 @@ extern (C) int UIAppMain(string[] args) { } else if (a.id == ACTION_FILE_OPEN) { UIString caption; caption = "Open Text File"d; - FileDialog dlg = new FileDialog(caption, window); + FileDialog dlg = new FileDialog(caption, window, null); dlg.onDialogResult = delegate(Dialog dlg, Action result) { Log.d("FileDialog.onDialogResult"); }; diff --git a/src/dlangui/core/events.d b/src/dlangui/core/events.d index d39ab105..240509db 100644 --- a/src/dlangui/core/events.d +++ b/src/dlangui/core/events.d @@ -93,7 +93,7 @@ class Action { return this; } /// deep copy constructor - this(Action a) { + this(immutable Action a) { _id = a._id; _label = a._label; _iconId = a._iconId; @@ -102,10 +102,11 @@ class Action { _accelerators[i] = a._accelerators[i]; _stringParam = a._stringParam; _longParam = a._longParam; - _objectParam = a._objectParam; + if (a._objectParam) + _objectParam = cast(Object)a._objectParam; } /// deep copy - @property Action clone() { return new Action(this); } + @property Action clone() immutable { return new Action(this); } /// create action only with ID this(int id) { _id = id; diff --git a/src/dlangui/dialogs/dialog.d b/src/dlangui/dialogs/dialog.d index b1e36289..68a6fb3d 100644 --- a/src/dlangui/dialogs/dialog.d +++ b/src/dlangui/dialogs/dialog.d @@ -43,6 +43,7 @@ class Dialog : VerticalLayout { protected Window _parentWindow; protected UIString _caption; protected uint _flags; + protected string _icon; Signal!DialogResultHandler onDialogResult; @@ -50,12 +51,28 @@ class Dialog : VerticalLayout { super("dlg"); _caption = caption; _parentWindow = parentWindow; + _flags = flags; + _icon = "dlangui-logo1"; + } + + /// get icon resource id + @property string windowIcon() { + return _icon; + } + + /// set icon resource id + @property Dialog windowIcon(string iconResourceId) { + _icon = iconResourceId; + if (_window && _icon) + _window.windowIcon = drawableCache.getImage(_icon); + return this; } @property UIString windowCaption() { return _caption; } + /// set window caption @property Dialog windowCaption(dstring caption) { _caption = caption; if (_window) @@ -63,6 +80,7 @@ class Dialog : VerticalLayout { return this; } + /// get window caption @property Dialog windowCaption(UIString caption) { _caption = caption; if (_window) @@ -74,6 +92,7 @@ class Dialog : VerticalLayout { Widget createButtonsPanel(const Action[] actions, int defaultActionIndex, int splitBeforeIndex) { LinearLayout res = new HorizontalLayout("buttons"); res.layoutWidth(FILL_PARENT); + res.layoutWeight = 0; for (int i = 0; i < actions.length; i++) { if (splitBeforeIndex == i) res.addChild(new HSpacer()); @@ -94,6 +113,24 @@ class Dialog : VerticalLayout { void init() { } + /** Notify about dialog result, and then close dialog. + + If onDialogResult listener is assigned, pass action to it. + + If no onDialogResult listener, pass to owner window. + + If action is null, no result dispatching will occur. + */ + void close(Action action) { + if (action) { + if (onDialogResult.assigned) + onDialogResult(this, action); + else if (_parentWindow) + _parentWindow.dispatchAction(action); + } + window.close(); + } + /// shows dialog void show() { init(); @@ -103,6 +140,8 @@ class Dialog : VerticalLayout { if (_flags & DialogFlag.Resizable) wflags |= WindowFlag.Resizable; _window = Platform.instance.createWindow(_caption, _parentWindow, wflags); + if (_window && _icon) + _window.windowIcon = drawableCache.getImage(_icon); _window.mainWidget = this; _window.show(); } diff --git a/src/dlangui/dialogs/filedlg.d b/src/dlangui/dialogs/filedlg.d index 8c3744e3..04f3a015 100644 --- a/src/dlangui/dialogs/filedlg.d +++ b/src/dlangui/dialogs/filedlg.d @@ -62,6 +62,7 @@ class FileDialog : Dialog, CustomGridCellAdapter { //protected StringGridWidget places; protected VerticalLayout leftPanel; protected VerticalLayout rightPanel; + protected Action _action; protected RootEntry[] _roots; protected string _path; @@ -69,8 +70,9 @@ class FileDialog : Dialog, CustomGridCellAdapter { protected DirEntry[] _entries; protected bool _isRoot; - this(UIString caption, Window parent, uint fileDialogFlags = DialogFlag.Modal | DialogFlag.Resizable | FileDialogFlag.FileMustExist) { + this(UIString caption, Window parent, Action action = null, uint fileDialogFlags = DialogFlag.Modal | DialogFlag.Resizable | FileDialogFlag.FileMustExist) { super(caption, parent, fileDialogFlags); + _action = action; } /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). @@ -173,6 +175,10 @@ class FileDialog : Dialog, CustomGridCellAdapter { if (e.isDir) { openDirectory(e.name); } else if (e.isFile) { + string fname = e.name; + Action result = ACTION_OPEN.clone(); + result.stringParam = fname; + close(result); } } diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index c165fe8c..bd50d1be 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -430,6 +430,18 @@ class Window { return (_mouseCaptureWidget !is null && isChild(_mouseCaptureWidget)); } + /// dispatch action to main widget + bool dispatchAction(Action action) { + Widget focus = focusedWidget; + // first, offer action to focused widget + if (focus && focus.handleAction(action)) + return true; + // if not processed by focused widget, pass to main widget + if (_mainWidget !is null) + return _mainWidget.handleAction(action); + return false; + } + /// dispatch mouse event to window content widgets bool dispatchMouseEvent(MouseEvent event) { // ignore events if there is no root diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index 046e7a79..c3ad6186 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -185,9 +185,13 @@ class SDLWindow : Window { Log.e("Trying to set null icon for window"); return; } - icon = new ColorDrawBuf(icon); - icon.invertAlpha(); - SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(icon.scanLine(0), icon.width, icon.height, 32, icon.width * 4, 0x00ff0000,0x0000ff00,0x000000ff,0xff000000); + int iconw = 32; + int iconh = 32; + ColorDrawBuf iconDraw = new ColorDrawBuf(iconw, iconh); + iconDraw.fill(0xE0E0E0); + iconDraw.drawRescaled(Rect(0, 0, iconw, iconh), icon, Rect(0, 0, icon.width, icon.height)); + iconDraw.invertAlpha(); + SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(iconDraw.scanLine(0), iconDraw.width, iconDraw.height, 32, iconDraw.width * 4, 0x00ff0000,0x0000ff00,0x000000ff,0xff000000); if (surface) { // The icon is attached to the window pointer SDL_SetWindowIcon(_win, surface); @@ -196,7 +200,7 @@ class SDLWindow : Window { } else { Log.e("failed to set window icon"); } - destroy(icon); + destroy(iconDraw); } /// after drawing, call to schedule redraw if animation is active @@ -818,11 +822,14 @@ class SDLPlatform : Platform { case SDL_WINDOWEVENT_RESIZED: Log.d("SDL_WINDOWEVENT_RESIZED win=", event.window.windowID, " pos=", event.window.data1, ",", event.window.data2); + w.onResize(event.window.data1, event.window.data2); + w.redraw(); break; case SDL_WINDOWEVENT_SIZE_CHANGED: Log.d("SDL_WINDOWEVENT_SIZE_CHANGED win=", event.window.windowID, " pos=", event.window.data1, ",", event.window.data2); w.onResize(event.window.data1, event.window.data2); + w.redraw(); break; case SDL_WINDOWEVENT_CLOSE: Log.d("SDL_WINDOWEVENT_CLOSE win=", event.window.windowID); diff --git a/src/dlangui/widgets/grid.d b/src/dlangui/widgets/grid.d index 222aa342..bfe23484 100644 --- a/src/dlangui/widgets/grid.d +++ b/src/dlangui/widgets/grid.d @@ -571,6 +571,8 @@ class GridWidgetBase : ScrollWidgetBase { scrolled = true; } else { while (rc.right > _clientRect.width && _scrollCol < _cols - _fixedCols - _headerCols - 1) { +// if (_scrollCol == _col) +// break; _scrollCol++; rc = cellRect(col, row); scrolled = true;