Changeset 37:052df9b2fe07
- Timestamp:
- 05/05/08 09:47:25 (8 months ago)
- Files:
-
- codeDoc/jobs.txt (modified) (1 diff)
- data/conf/gui.mtt (modified) (1 diff)
- mde/gui/renderer/IRenderer.d (modified) (1 diff)
- mde/gui/renderer/SimpleRenderer.d (modified) (1 diff)
- mde/gui/widget/Ifaces.d (modified) (2 diffs)
- mde/gui/widget/Widget.d (modified) (5 diffs)
- mde/gui/widget/Window.d (modified) (4 diffs)
- mde/gui/widget/createWidget.d (modified) (2 diffs)
- mde/gui/widget/layout.d (modified) (6 diffs)
- mde/input/Input.d (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
codeDoc/jobs.txt
r36 r37 49 49 50 50 Done (for git log message): 51 Renamed mde.global to mde.imde.52 Enabled drawing on demand.53 Allowed options to take double values.54 Made the main loop's polling interval (sleep duration) settable from config files.data/conf/gui.mtt
r36 r37 4 4 <int|x=30> 5 5 <int|y=80> 6 <int[][int]|widgetData=[0:[ 1003,200,200]]>6 <int[][int]|widgetData=[0:[0x4010,200,200]]> 7 7 {W2} 8 8 <int|x=150> 9 9 <int|y=200> 10 <int[][int]|widgetData=[0:[ 1002,1,3,2,3,5],2:[1001,150,150],3:[1003,150,150],5:[1002,2,1,6,6],6:[1003,73,73]]>10 <int[][int]|widgetData=[0:[0xB004,1,3,2,3,5],2:[0x1,150,150],3:[0x4010,100,100],5:[0xB004,3,1,6,1,6],6:[0x4010,60,60],1:[0x3001]]> mde/gui/renderer/IRenderer.d
r32 r37 41 41 void drawWidgetBack (int x, int y, int w, int h); 42 42 43 /** Draw a basic box. Doesn't set the colour. Eventually to be removed. */44 void drawB ox (int x, int y, int w, int h);43 /** Draws a button frame, in if pushed == true. */ 44 void drawButton (int x, int y, int w, int h, bool pushed); 45 45 //END draw routines 46 46 } mde/gui/renderer/SimpleRenderer.d
r32 r37 49 49 void drawWidgetBack (int x, int y, int w, int h) {} 50 50 51 void drawBox (int x, int y, int w, int h) { 51 void drawButton (int x, int y, int w, int h, bool pushed) { 52 if (pushed) 53 gl.setColor (1f, 0f, 1f); 54 else 55 gl.setColor (.6f, 0f, .6f); 52 56 gl.drawBox (x,y, w,h); 53 57 } mde/gui/widget/Ifaces.d
r36 r37 66 66 * widget, and data is an array of initialisation data. The method should throw a 67 67 * WidgetDataException (created without parameters) if the data has wrong length or is otherwise 68 * invalid. */ 68 * invalid. 69 * 70 * The widget's size should be set either by it's this() method or by the first call to 71 * setSize(). setSize() is called on all widgets immediately after their creation, and throwing an 72 * exception at this point (but not on later calls to setSize) is an acceptible method of failure. 73 */ 74 //NOTE: add another this() without the data for default initialization, for the GUI editor? 69 75 interface IWidget 70 76 { 71 /** Calculate the minimum size the widget could be shrunk to, taking into account 77 /** is the width / height resizable? 78 * 79 * If not, the widget has fixed dimensions equal the output of getMinimalSize. */ 80 bool isWSizable (); 81 bool isHSizable (); /// ditto 82 83 /** Calculate the minimal size the widget could be shrunk to, taking into account 72 84 * child-widgets. */ 73 void getMinim umSize (out int w, out int h);85 void getMinimalSize (out int w, out int h); 74 86 75 /** Get the current size of the widget. 87 /** Get the current size of the widget. */ 88 void getCurrentSize (out int w, out int h); 89 90 /** Used to adjust the size. 76 91 * 77 * On the first call (during loading), this may be a value saved as part of the config or 78 * something else (e.g. revert to getMinimumSize). */ 79 void getCurrentSize (out int w, out int h); 92 * The size should be clamped to the widget's minimal size, i.e. the size set may be larger 93 * than that given by the parameters. Conversely, the size should not be reduced to the 94 * widget's maximal size (if any) but expanded as necessary (alignment to be implemented). 95 * 96 * If the actual size is needed, call getCurrentSize afterwards. */ 97 void setSize (int w, int h); 80 98 81 99 /** Set the current position (i.e. called on init and move). */ 82 100 void setPosition (int x, int y); 101 83 102 84 103 /** Recursively scan the widget tree to find the widget under (x,y). … … 101 120 void clickEvent (ushort cx, ushort cy, ubyte b, bool state); 102 121 122 103 123 /** Draw, using the stored values of x and y. 104 124 * mde/gui/widget/Widget.d
r36 r37 21 21 import mde.gui.exception; 22 22 23 import gl = mde.gl.basic;24 25 23 import tango.io.Stdout; 26 24 27 /** A base widget class. Widgets need not inherit this (they only need implement IWidget), but this 28 * class provides a useful basic implementation for widgets. 25 /** An abstract base widget class. 29 26 * 30 * Do not use directly (i.e. only for inheriting from). 31 */ 32 class Widget : IWidget 27 * This abstract class, and the more concrete FixedWidget and ScalableWidget classes provides a 28 * useful basic implementation for widgets. Widgets need not inherit these (they only need implement 29 * IWidget); they are simply provided for convenience and to promote code reuse. */ 30 abstract class Widget : IWidget 33 31 { 34 /** Minimum size is zero. */ 35 void getMinimumSize (out int w, out int h) {} // w,h initialised to 0 36 /** Current size. */ 37 void getCurrentSize (out int w, out int h) { 38 w = this.w; 39 h = this.h; 32 void getCurrentSize (out int cw, out int ch) { 33 cw = w; 34 ch = h; 40 35 } 41 36 42 void setPosition (int x, inty) {43 this.x =x;44 this.y =y;37 void setPosition (int nx, int ny) { 38 x = nx; 39 y = ny; 45 40 } 46 41 47 /* *Return self, since we don't have child widgets and the method wouldn't have been called42 /* Return self, since we don't have child widgets and the method wouldn't have been called 48 43 * unless the location was over us. Valid for all widgets without children. */ 49 44 IWidget getWidget (int,int) { … … 51 46 } 52 47 53 /* *Dummy event method (widget doesn't respond to events) */48 /* Dummy event method (widget doesn't respond to events) */ 54 49 void clickEvent (ushort cx, ushort cy, ubyte b, bool state) {} 55 50 56 /* *Basic draw method: draw the background (all widgets should do this) */51 /* Basic draw method: draw the background (all widgets should do this) */ 57 52 void draw () { 58 53 window.renderer.drawWidgetBack (x,y, w,h); … … 64 59 int w, h; // size 65 60 } 61 /** A base for fixed-size widgets. */ 62 class FixedWidget : Widget { 63 bool isWSizable () { return false; } 64 bool isHSizable () { return false; } 65 66 /* Not resizable, so return current size. */ 67 void getMinimalSize (out int mw, out int mh) { 68 mw = wF; 69 mh = hF; 70 } 71 72 /* Ignore: a fixed size widget. */ 73 void setSize (int nw, int nh) { 74 w = (nw >= wF ? nw : wF); 75 h = (nh >= hF ? nh : hF); 76 } 77 78 protected: 79 int wF, hF; // The "fixed" size, i.e. the preferred & minimal size 80 } 81 /** A base for resizable widgets. */ 82 class SizableWidget : Widget { 83 bool isWSizable () { return true; } 84 bool isHSizable () { return true; } 85 86 /* Return zero. */ 87 void getMinimalSize (out int mw, out int mh) {} 88 89 /* Set size: a fully resizable widget. */ 90 void setSize (int nw, int nh) { 91 w = (nw >= 0 ? nw : 0); 92 h = (nh >= 0 ? nh : 0); 93 } 94 } 66 95 67 96 //BEGIN Widgets 68 /// Draws a box. That's it.69 class BoxWidget :Widget97 /// A fixed-size blank widget. 98 class FixedBlankWidget : FixedWidget 70 99 { 71 100 this (IWindow wind, IWidget, int[] data) { … … 74 103 window = wind; 75 104 76 w = data[0];77 h = data[1];105 w = wF = data[0]; 106 h = hF = data[1]; 78 107 } 79 void draw () { 80 gl.setColor(1f,0f,0f); 81 window.renderer.drawBox (x,y, w,h); 108 } 109 110 /// A completely resizable blank widget (initial size zero). 111 class SizableBlankWidget : SizableWidget 112 { 113 this (IWindow wind, IWidget, int[] data) { 114 if (data.length != 0) throw new WidgetDataException; 115 116 window = wind; 82 117 } 83 118 } 84 119 85 120 /// First interactible widget 86 class ButtonWidget : Widget121 class ButtonWidget : FixedWidget 87 122 { 88 123 bool pushed = false; // true if button is pushed in (visually) … … 95 130 window = wind; 96 131 97 w = data[0];98 h = data[1];132 w = wF = data[0]; 133 h = hF = data[1]; 99 134 } 100 135 101 136 void draw () { 102 if (pushed) 103 gl.setColor (1f, 0f, 1f); 104 else 105 gl.setColor (.6f, 0f, .6f); 106 window.renderer.drawBox (x,y, w,h); 107 } 108 109 void getMinimumSize (out int w, out int h) { 110 w = this.w; // button is not resizable 111 h = this.h; 137 window.renderer.drawButton (x,y, w,h, pushed); 112 138 } 113 139 mde/gui/widget/Window.d
r36 r37 53 53 /** Call after loading is finished to setup the window and confirm that it's valid. 54 54 * 55 * Throws: WindowLoadException. Do not use the instance in this case! */ 55 * Throws: WindowLoadException (or possibly other exceptions). Do not use the instance if an 56 * exception occurs! */ 56 57 void finalise (IGui gui) 57 58 in { … … 65 66 66 67 // Create the primary widget (and indirectly all sub-widgets), throwing on error: 67 widget = makeWidget (0, this);// primary widget always has ID 0. 68 69 widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) 70 71 widgetX = x + rend.windowBorder; // widget position 72 widgetY = y + rend.windowBorder; // must be updated if the window is moved 68 widget = makeWidget (0, this); // primary widget always has ID 0. 69 widgetData = null; // data is no longer needed: allow GC to collect (cannot safely delete) 70 71 widget.setSize (0,0); // set the minimal size 72 widget.getCurrentSize (w,h); // and get this size 73 w += rend.windowBorder * 2; // Adjust for border 74 h += rend.windowBorder * 2; 75 76 widgetX = x + rend.windowBorder; // widget position 77 widgetY = y + rend.windowBorder; // must be updated if the window is moved 73 78 widget.setPosition (widgetX, widgetY); 74 75 widget.getCurrentSize (w,h);// Find the initial size76 w += rend.windowBorder * 2; // Adjust for border77 h += rend.windowBorder * 2;78 79 79 80 xw = x+w; … … 134 135 135 136 //BEGIN IWidget methods 136 void getMinimumSize (out int w, out int h) { 137 widget.getMinimumSize (x,y); 138 w += rend.windowBorder * 2; // Adjust for border 139 h += rend.windowBorder * 2; 137 bool isWSizable () { 138 return widget.isWSizable; 139 } 140 bool isHSizable () { 141 return widget.isHSizable; 142 } 143 144 void getMinimalSize (out int mw, out int mh) { 145 mw = w + rend.windowBorder * 2; 146 mh = h + rend.windowBorder * 2; 140 147 } 141 148 void getCurrentSize (out int cw, out int ch) { … … 144 151 } 145 152 146 void setPosition (int x, int y) { 147 // Currently only used internally 148 this.x = x; 149 this.y = y; 153 void setSize (int nw, int nh) { 154 w = nw; 155 h = nh; 156 157 xw = x+w; 158 yh = y+h; 159 160 widget.setSize (w - rend.windowBorder * 2, h - rend.windowBorder * 2); 161 } 162 163 void setPosition (int nx, int ny) { 164 x = nx; 165 y = ny; 150 166 151 167 xw = x+w; mde/gui/widget/createWidget.d
r34 r37 23 23 import mde.gui.exception : WidgetDataException; 24 24 25 //BEGIN createWidget26 /// Widget types. Start high so they can be reordered easily later.27 enum WIDGET_TYPE : int {28 BOX = 1001, GRID, BUTTON29 }30 31 25 /** Create a widget of type data[0] (see enum WIDGET_TYPES) for _window window, with initialisation 32 26 * data [1..$]. */ … … 40 34 data = data[1..$]; // the rest is passed to the Widget 41 35 42 if (type == WIDGET_TYPE.BOX) return new BoxWidget (window, parent, data); 43 else if (type == WIDGET_TYPE.GRID) return new GridWidget (window, parent, data); 44 else if (type == WIDGET_TYPE.BUTTON) return new ButtonWidget (window, parent, data); 45 else throw new WidgetDataException ("Bad widget type"); 36 mixin (binarySearch ("type", WIDGETS)); 37 throw new WidgetDataException ("Bad widget type"); 46 38 } 47 //END createWidget 39 40 /+ for converting to a char[] name (unused) 41 static this() { 42 WIDGET_NAMES = [ 43 FixedBlank : "FixedBlank", 44 SizableBlank : "SizableBlank", 45 Button : "Button", 46 GridLayout : "GridLayout" 47 ]; 48 }+/ 49 50 private: 51 /// Widget types. 52 enum WIDGET_TYPE : int { 53 WSIZABLE = 0x1000, // horizontally resizable 54 HSIZABLE = 0x2000, // vertically resizable 55 INTERACTIBLE = 0x4000, // any specific interaction 56 LAYOUT = 0x8000, // is a layout widget (i.e. has sub-widgets)? 57 58 // Use widget names rather than usual capitals convention 59 60 // blank: 0x1 61 FixedBlank = 0x1, 62 SizableBlank = WSIZABLE | HSIZABLE | 0x1, 63 64 // buttons: 0x10 65 Button = INTERACTIBLE | 0x10, 66 67 GridLayout = LAYOUT | WSIZABLE | HSIZABLE | 0x4 68 } 69 70 //const char[][int] WIDGET_NAMES; 71 72 // Only used for binarySearch algorithm generation; must be ordered by numerical values. 73 const char[][] WIDGETS = [ 74 "FixedBlank", 75 "SizableBlank", 76 "Button", 77 "GridLayout" ]; 78 79 // Purely to add indentation. Could just return "" without affecting functionality. 80 /+static char[] indent (uint i) { 81 char[] ret; 82 for (; i > 0; --i) ret ~= " "; 83 // This is not executable at compile time: 84 //ret.length = i * 4; // number of characters for each indentation 85 //ret[] = ' '; // character to indent with 86 return ret; 87 }+/ 88 char[] indent (uint) { return ""; } 89 90 /* Generates a binary search algorithm. */ 91 char[] binarySearch (char[] var, char[][] consts, int indents = 0) { 92 if (consts.length > 3) { 93 return indent(indents) ~ "if (" ~ var ~ " <= WIDGET_TYPE." ~ consts[$/2 - 1] ~ ") {\n" ~ 94 binarySearch (var, consts[0 .. $/2], indents + 1) ~ 95 indent(indents) ~ "} else {\n" ~ 96 binarySearch (var, consts[$/2 .. $], indents + 1) ~ 97 indent(indents) ~ "}\n"; 98 } else { 99 char[] ret; 100 ret ~= indent(indents); 101 foreach (c; consts) { 102 ret ~= "if (" ~ var ~ " == WIDGET_TYPE." ~ c ~ ") {\n" ~ 103 indent(indents+1) ~ "return new " ~ c ~ "Widget (window, parent, data);\n" ~ 104 indent(indents) ~ "} else "; 105 } 106 ret = ret[0..$-6] ~ '\n'; // remove last else 107 return ret; 108 } 109 } mde/gui/widget/layout.d
r34 r37 20 20 import mde.gui.exception : WidgetDataException; 21 21 22 /// Encapsulates a grid of Widgets 23 class GridWidget : Widget 22 /** Encapsulates a grid of Widgets. 23 * 24 * Since a grid with either dimension zero is not useful, there must be at least one sub-widget. */ 25 class GridLayoutWidget : Widget 24 26 { 25 27 this (IWindow wind, IWidget, int[] data) { 26 // Get grid size 27 if (data.length < 2) throw new WidgetDataException; 28 // Get grid size and check data 29 // Check sufficient data for rows, cols, and at least one widget: 30 if (data.length < 3) throw new WidgetDataException; 28 31 rows = data[0]; 29 32 cols = data[1]; 33 if (data.length != 2 + rows * cols) throw new WidgetDataException; 34 /* data.length >= 3 so besides checking the length is correct, this tells us: 35 * rows * cols >= 3 - 2 = 1 a free check! 36 * The only thing not checked is whether both rows and cols are negative, which would 37 * cause an exception when dynamic arrays are allocated later (and is unlikely). */ 30 38 31 39 window = wind; 32 40 33 41 // Get all sub-widgets 34 // Check: correct data length and rows*cols >= 0 (know data.length - 2 >= 0).35 if (data.length != 2 + rows * cols) throw new WidgetDataException;36 42 subWidgets.length = rows*cols; 37 43 foreach (i, inout subWidget; subWidgets) { 38 44 subWidget = window.makeWidget (data[i+2], this); 39 45 } 40 41 getMinimumSize (w,h); // Calculate the size (current size is not saved) 42 } 43 44 // Calculates from all rows and columns of widgets. 45 void getMinimumSize (out int w, out int h) { 46 if (rows*cols == 0) { // special case 47 w = h = 0; 48 return; 49 } 50 51 // Find the sizes of all subWidgets 52 int[] widgetW = new int[subWidgets.length]; // dimensions 53 int[] widgetH = new int[subWidgets.length]; 54 foreach (i,widget; subWidgets) widget.getCurrentSize (widgetW[i],widgetH[i]); 55 56 // Find row heights and column widths (non cumulative) 57 rowH.length = rows; 58 colW.length = cols; //WARNING: code reliant on these being initialised to zero 59 for (uint i = 0; i < subWidgets.length; ++i) { 60 uint n = i / cols; // row 61 if (rowH[n] < widgetH[i]) rowH[n] = widgetH[i]; 62 n = i % cols; // column 63 if (colW[n] < widgetW[i]) colW[n] = widgetW[i]; 64 } 65 66 // rowY / colX 46 } 47 48 bool isWSizable () { 49 if (colSizable == -2) { // check whether any columns are resizable 50 for1: 51 for (uint i = 0; i < cols; ++i) { // for each column 52 for (uint j = 0; j < subWidgets.length; j += cols) // for each row 53 if (!subWidgets[i+j].isWSizable) // column not resizable 54 continue for1; // continue the outer for loop 55 56 // column is resizable if we get to here 57 colSizable = i; 58 goto break1; // use goto in lieu of for...else 59 } 60 61 // if we get here, no resizable column was found 62 colSizable = -1; 63 64 break1:; 65 } 66 67 if (colSizable >= 0) return true; 68 else return false; 69 } 70 71 bool isHSizable () { 72 if (rowSizable == -2) { // check whether any columns are resizable 73 for2: 74 for (uint i = 0; i < subWidgets.length; i += cols) { // for each row 75 for (uint j = 0; j < cols; ++j) // for each column 76 if (!subWidgets[i+j].isHSizable) 77 continue for2; 78 79 rowSizable = i / cols; // the current row 80 goto break2; 81 } 82 83 rowSizable = -1; 84 85 break2:; 86 } 87 88 if (rowSizable >= 0) return true; 89 else return false; 90 } 91 92 /* Calculates the minimal size from all rows and columns of widgets. */ 93 void getMinimalSize (out int mw, out int mh) { 94 // If rowHMin & colWMin are null, calculate them. They are set null whenever the contents 95 // or the contents' minimal size change, as well as when this widget is created. 96 if (rowHMin is null) 97 genMinRowColSizes; 98 99 // Calculate the size, starting with the spacing: 100 mh = window.renderer.layoutSpacing; // use temporarily 101 mw = mh * (cols - 1); 102 mh *= (rows - 1); 103 104 foreach (x; colWMin) // add the column/row's dimensions 105 mw += x; 106 foreach (x; rowHMin) 107 mh += x; 108 } 109 110 void setSize (int nw, int nh) { 111 // Step 1: calculate the minimal row/column sizes. 112 int mw, mh; // FIXME: use w,h directly? 113 getMinimalSize (mw, mh); 114 colW = colWMin; // start with these dimensions, and increase if necessary 115 rowH = rowHMin; 116 117 // Step 2: clamp nw/nh or expand a column/row to achieve the required size 118 if (nw <= mw) nw = mw; // clamp to minimal size 119 else { 120 if (isWSizable) // calculates colSizable; true if any is resizable 121 colW[colSizable] += nw - mw; // new width 122 else // no resizable column; so force the last one 123 colW[$-1] += nw - mw; 124 } 125 126 if (nh <= mh) nh = mh; 127 else { 128 if (isHSizable) 129 rowH[rowSizable] += nh - mh; 130 else 131 rowH[$-1] += nh - mh; 132 } 133 134 // Step 3: set each sub-widget's size. 135 foreach (i,widget; subWidgets) 136 widget.setSize (colW[i % cols], rowH[i / cols]); 137 138 // Step 4: calculate the column and row positions 139 colX.length = cols; 67 140 rowY.length = rows; 68 colX.length = cols;69 141 int spacing = window.renderer.layoutSpacing; 70 142 … … 74 146 cum += x + spacing; 75 147 } 76 h = cum - spacing; // total height 148 h = cum - spacing; // set the total height 149 assert (h == nh); // FIXME: remove and set w/h directly once this is asserted 150 77 151 cum = 0; 78 152 foreach (i, x; colW) { … … 81 155 } 82 156 w = cum - spacing; // total width 157 assert (w == nw); 83 158 } 84 159 … … 91 166 } 92 167 168 93 169 // Find the relevant widget. 94 170 IWidget getWidget (int cx, int cy) { 95 if (rows*cols == 0) return this; // special case96 97 171 int lx = cx - x, ly = cy - y; // use coords relative to this widget 98 172 … … 120 194 if (lx < i && ly < j) 121 195 return widg.getWidget (cx, cy); 196 return this; // wasn't in cell 122 197 } 123 198 … … 129 204 } 130 205 206 private: 207 void genMinRowColSizes () { 208 // Find the sizes of all subWidgets 209 int[] widgetW = new int[subWidgets.length]; // dimensions 210 int[] widgetH = new int[subWidgets.length]; 211 foreach (i,widget; subWidgets) 212 widget.getMinimalSize (widgetW[i],widgetH[i]); 213 214 // Find the minimal row heights and column widths (non cumulative) 215 colWMin = new int[cols]; // set length 216 rowHMin = new int[rows]; 217 for (uint i = 0; i < subWidgets.length; ++i) { 218 uint n; 219 n = i % cols; // column 220 if (colWMin[n] < widgetW[i]) colWMin[n] = widgetW[i]; 221 n = i / cols; // row 222 if (rowHMin[n] < widgetH[i]) rowHMin[n] = widgetH[i]; 223 } 224 } 225 131 226 protected: 132 int rows, cols; // number of cells in grid 227 int cols, rows; // number of cells in grid 228 229 int colSizable = -2;// 0..cols-1 means this column is resizable 230 int rowSizable = -2;// -2 means not calculated yet, -1 means not resizable 231 232 int[] colWMin; // minimal column width 233 int[] rowHMin; // minimal row height 234 int[] colW; // column width (widest widget) 133 235 int[] rowH; // row height (highest widget in the row) 134 int[] colW; // column width (widest widget) 135 int[] rowY; // cumulative rowH[i-1] + border and padding 136 int[] colX; // cumulative colW[i-1] + border and padding 236 237 int[] colX; // cumulative colW[i-1] + padding (add x to get column's left x-coord) 238 int[] rowY; // cumulative rowH[i-1] + padding 239 137 240 IWidget[] subWidgets; // all widgets in the grid (by row): 138 241 /* SubWidget order: [ 0 1 ] mde/input/Input.d
r34 r37 197 197 case SDL_MOUSEBUTTONDOWN: 198 198 case SDL_MOUSEBUTTONUP: 199 foreach (dg; mouseClickCallbacks) 200 dg (event.button.x - 1, event.button.y - 1, 201 event.button.button, event.button.state == SDL_PRESSED); 199 foreach (dg; mouseClickCallbacks) { 200 try 201 dg (event.button.x - 1, event.button.y - 1, 202 event.button.button, event.button.state == SDL_PRESSED); 203 catch (Exception e) 204 logger.error (CB_EXC ~ e.msg); 205 } 202 206 break; 203 207 … … 206 210 mouse_y = event.motion.y - 1; 207 211 208 foreach (dg; mouseMotionCallbacks) 209 dg (event.motion.x - 1, event.motion.y - 1); 212 foreach (dg; mouseMotionCallbacks) { 213 try 214 dg (event.motion.x - 1, event.motion.y - 1); 215 catch (Exception e) 216 logger.error (CB_EXC ~ e.msg); 217 } 210 218 break; 211 219 … … 370 378 } 371 379 380 static const CB_EXC = "Callback exception: "; 381 372 382 static Logger logger; 373 383 … … 486 496 487 497 ButtonCallback[]* cb_p = id in myThis.buttonCallbacks; 488 if (cb_p) foreach (cb; *cb_p) cb (id, b); 498 if (cb_p) foreach (cb; *cb_p) { 499 try 500 cb (id, b); 501 catch (Exception e) 502 logger.error (CB_EXC ~ e.msg); 503 } 489 504 } 490 505 // Adjuster to check modifier keys … … 498 513 499 514 AxisCallback[]* cb_p = id in myThis.axisCallbacks; 500 if (cb_p) foreach (cb; *cb_p) cb (id, x); 515 if (cb_p) foreach (cb; *cb_p) { 516 try 517 cb (id, x); 518 catch (Exception e) 519 logger.error (CB_EXC ~ e.msg); 520 } 501 521 } 502 522 … … 513 533 514 534 RelMotionCallback[]* cb_p = id in myThis.relMotionCallbacks; 515 if (cb_p) foreach (cb; *cb_p) cb (id, x,y); 535 if (cb_p) foreach (cb; *cb_p) { 536 try 537 cb (id, x,y); 538 catch (Exception e) 539 logger.error (CB_EXC ~ e.msg); 540 } 516 541 } 517 542 //END ES Functions
