Changeset 43:1530d9c04d4d
- Timestamp:
- 05/15/08 05:39:57
(8 months ago)
- Author:
- Diggory Hardy <diggory.hardy@gmail.com>
- branch:
- default
- convert_revision:
- 3f46d85fe9161935762020890cfc39ce37d3e422
- Message:
Column/row resizing implemented for GridLayoutWidget? (finally)!
Also new exitImmediately option and a few debug scope(failure) log messages.
committer: Diggory Hardy <diggory.hardy@gmail.com>
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r41 |
r43 |
|
| 4 | 4 | |
|---|
| 5 | 5 | In progress: |
|---|
| 6 | | Implement row/col sizing. |
|---|
| 7 | 6 | |
|---|
| 8 | 7 | |
|---|
| … | … | |
| 10 | 9 | To do (importance 0-5: 0 pointless, 1 no obvious impact now, 2 todo sometime, 3 useful, 4 important, 5 urgent): |
|---|
| 11 | 10 | Also see todo.txt and FIXME/NOTE comment marks. |
|---|
| | 11 | 4 Not guaranteed to catch up-click ending callback! Appears not to be a problem... |
|---|
| 12 | 12 | 4 OutOfMemoryException is not currently checked for â it should be at least in critical places (use high-level catching of all errors?). |
|---|
| 13 | 13 | 3 on-event draw support (mde.events and GUI need to tell mde.mde) |
|---|
| … | … | |
| 15 | 15 | 3 Update scheduler as outlined in FIXME. |
|---|
| 16 | 16 | 3 Windows building/compatibility (currently partial) |
|---|
| | 17 | 2 Options need a "level": simple options, for advanced users, for debugging only, etc. |
|---|
| 17 | 18 | 2 Command-line options for paths to by-pass normal path finding functionality. |
|---|
| 18 | 19 | 2 Consider replacing byte/short types with int type |
|---|
| … | … | |
| 50 | 51 | |
|---|
| 51 | 52 | Done (for git log message): |
|---|
| 52 | | The renderer now controls which parts of the window border allow resizing. |
|---|
| r29 |
r43 |
|
| 4 | 4 | <entry|logLevel=["Logging level","Controls which messages are logged, from 0=trace to 6=none (default: 1=info)."]> |
|---|
| 5 | 5 | <entry|L10n=["Localisation","Specifies the language to use."]> |
|---|
| | 6 | <entry|pollInterval=["Polling interval","Delay in main loop to limit CPU usage"]> |
|---|
| | 7 | <entry|exitImmediately=["Exit immediately","Load files and exit immediately, without running main loop (for debugging)"]> |
|---|
| r40 |
r43 |
|
| 4 | 4 | <int|x=30> |
|---|
| 5 | 5 | <int|y=80> |
|---|
| 6 | | <int[][int]|widgetData=[0:[0x4010,200,200]]> |
|---|
| | 6 | <int[][int]|widgetData=[0:[0xB004,2,1,1,2],1:[0x4010,200,200],2:[0x1,100,100]]> |
|---|
| 7 | 7 | {W2} |
|---|
| 8 | 8 | <int|x=150> |
|---|
| r36 |
r43 |
|
| 2 | 2 | {misc} |
|---|
| 3 | 3 | <bool|useThreads=false> |
|---|
| | 4 | <bool|exitImmediately=false> |
|---|
| 4 | 5 | <char[]|L10n="en-GB"> |
|---|
| 5 | | <int|logLevel=0> |
|---|
| | 6 | <int|logLevel=1> |
|---|
| 6 | 7 | <double|pollInterval=0.01> |
|---|
| 7 | 8 | |
|---|
| r36 |
r43 |
|
| 342 | 342 | OptionsMisc miscOpts; |
|---|
| 343 | 343 | class OptionsMisc : Options { |
|---|
| 344 | | alias store!("useThreads") BOOL; |
|---|
| | 344 | alias store!("useThreads", "exitImmediately") BOOL; |
|---|
| 345 | 345 | alias store!("logLevel") INT; |
|---|
| 346 | 346 | alias store!("pollInterval") DOUBLE; |
|---|
| r41 |
r43 |
|
| 146 | 146 | * Sends the event on to the relevant windows and all click callbacks. */ |
|---|
| 147 | 147 | void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { |
|---|
| | 148 | debug scope (failure) |
|---|
| | 149 | logger.warn ("clickEvent: failed!"); |
|---|
| 148 | 150 | // NOTE: buttons receive the up-event even when drag-callbacks are in place. |
|---|
| 149 | 151 | foreach (dg; clickCallbacks) |
|---|
| … | … | |
| 166 | 168 | * Sends the event on to all motion callbacks. */ |
|---|
| 167 | 169 | void motionEvent (ushort cx, ushort cy) { |
|---|
| | 170 | debug scope (failure) |
|---|
| | 171 | logger.warn ("motionEvent: failed!"); |
|---|
| 168 | 172 | foreach (dg; motionCallbacks) |
|---|
| 169 | 173 | dg (cx, cy); |
|---|
| r41 |
r43 |
|
| 75 | 75 | void drawWidgetBack (int x, int y, int w, int h); |
|---|
| 76 | 76 | |
|---|
| | 77 | /** Draws a blank widget (temporary) */ |
|---|
| | 78 | void drawBlank (int x, int y, int w, int h); |
|---|
| | 79 | |
|---|
| 77 | 80 | /** Draws a button frame, in if pushed == true. */ |
|---|
| 78 | 81 | void drawButton (int x, int y, int w, int h, bool pushed); |
|---|
| r41 |
r43 |
|
| 94 | 94 | void drawWidgetBack (int x, int y, int w, int h) {} |
|---|
| 95 | 95 | |
|---|
| | 96 | void drawBlank (int x, int y, int w, int h) { |
|---|
| | 97 | gl.setColor (.4f, .4f, .4f); |
|---|
| | 98 | gl.drawBox (x,y, w,h); |
|---|
| | 99 | } |
|---|
| | 100 | |
|---|
| 96 | 101 | void drawButton (int x, int y, int w, int h, bool pushed) { |
|---|
| 97 | 102 | if (pushed) |
|---|
| r41 |
r43 |
|
| 129 | 129 | h = (nh >= 0 ? nh : 0); |
|---|
| 130 | 130 | } |
|---|
| | 131 | |
|---|
| | 132 | void draw () { |
|---|
| | 133 | super.draw; |
|---|
| | 134 | |
|---|
| | 135 | window.renderer.drawBlank (x,y, w,h); |
|---|
| | 136 | } |
|---|
| 131 | 137 | } |
|---|
| 132 | 138 | |
|---|
| … | … | |
| 138 | 144 | if (data.length != 3) throw new WidgetDataException; |
|---|
| 139 | 145 | super (wind, data); |
|---|
| | 146 | } |
|---|
| | 147 | void draw () { |
|---|
| | 148 | super.draw; |
|---|
| | 149 | |
|---|
| | 150 | window.renderer.drawBlank (x,y, w,h); |
|---|
| 140 | 151 | } |
|---|
| 141 | 152 | } |
|---|
| … | … | |
| 176 | 187 | // Called when a mouse motion/click event occurs while (held == true) |
|---|
| 177 | 188 | bool clickWhileHeld (ushort cx, ushort cy, ubyte b, bool state) { |
|---|
| 178 | | //NOTE: which button? test |
|---|
| 179 | | if (cx >= x && cx < x+w && cy >= y && cy < y+h) // button event |
|---|
| 180 | | Stdout ("Button clicked!").newline; |
|---|
| 181 | | |
|---|
| 182 | | pushed = false; |
|---|
| 183 | | window.requestRedraw; |
|---|
| 184 | | window.gui.removeCallbacks (cast(void*) this); |
|---|
| 185 | | |
|---|
| | 189 | if (b == 1 && state == false) { |
|---|
| | 190 | if (cx >= x && cx < x+w && cy >= y && cy < y+h) // button event |
|---|
| | 191 | Stdout ("Button clicked!").newline; |
|---|
| | 192 | |
|---|
| | 193 | pushed = false; |
|---|
| | 194 | window.requestRedraw; |
|---|
| | 195 | window.gui.removeCallbacks (cast(void*) this); |
|---|
| | 196 | |
|---|
| | 197 | return true; |
|---|
| | 198 | } |
|---|
| 186 | 199 | return false; |
|---|
| 187 | 200 | } |
|---|
| r42 |
r43 |
|
| 19 | 19 | import mde.gui.widget.Widget; |
|---|
| 20 | 20 | import mde.gui.exception; |
|---|
| | 21 | |
|---|
| | 22 | import tango.io.Stdout; |
|---|
| | 23 | debug { |
|---|
| | 24 | import tango.util.log.Log : Log, Logger; |
|---|
| | 25 | private Logger logger; |
|---|
| | 26 | static this () { |
|---|
| | 27 | logger = Log.getLogger ("mde.gui.widget.layout"); |
|---|
| | 28 | } |
|---|
| | 29 | } |
|---|
| 21 | 30 | |
|---|
| 22 | 31 | /** Encapsulates a grid of Widgets. |
|---|
| … | … | |
| 59 | 68 | data = widget.adjust (data); |
|---|
| 60 | 69 | |
|---|
| 61 | | // colWMin/rowHMin are needed as absolute quantities in this function: |
|---|
| 62 | | int[] cwMin = new int[colWMin.length]; |
|---|
| 63 | | foreach (i,x; colWMin) |
|---|
| 64 | | cwMin[i] = x>=0 ? x : -x; |
|---|
| 65 | | int[] rhMin = new int[rowHMin.length]; |
|---|
| 66 | | foreach (i,x; rowHMin) |
|---|
| 67 | | rhMin[i] = x>=0 ? x : -x; |
|---|
| 68 | | |
|---|
| 69 | 70 | /* We basically short-cut setSize by loading previous col/row sizes and doing the final |
|---|
| 70 | 71 | * calculations. |
|---|
| … | … | |
| 74 | 75 | int lenUsed = 0; |
|---|
| 75 | 76 | if (data.length < rows + cols) { // data error; use defaults |
|---|
| 76 | | colW = cwMin; |
|---|
| 77 | | rowH = rhMin; |
|---|
| | 77 | colW = colWMin.dup; |
|---|
| | 78 | rowH = rowHMin.dup; |
|---|
| 78 | 79 | } else { // sufficient data |
|---|
| 79 | 80 | lenUsed = rows+cols; |
|---|
| … | … | |
| 85 | 86 | //NOTE: could also check non-resizable sizes are not too large |
|---|
| 86 | 87 | foreach (i, ref w; colW) |
|---|
| 87 | | if (w < cwMin[i]) w = cwMin[i]; |
|---|
| | 88 | if (w < colWMin[i]) w = colWMin[i]; |
|---|
| 88 | 89 | foreach (i, ref h; rowH) |
|---|
| 89 | | if (h < rhMin[i]) h = rhMin[i]; |
|---|
| | 90 | if (h < rowHMin[i]) h = rowHMin[i]; |
|---|
| 90 | 91 | } |
|---|
| 91 | 92 | |
|---|
| … | … | |
| 118 | 119 | |
|---|
| 119 | 120 | bool isWSizable () { |
|---|
| 120 | | // True if any column is resizable: |
|---|
| 121 | | foreach (d; colWMin) |
|---|
| 122 | | if (d >= 0) |
|---|
| 123 | | return true; |
|---|
| 124 | | return false; |
|---|
| | 121 | return (sizableCols.length != 0); |
|---|
| 125 | 122 | } |
|---|
| 126 | 123 | |
|---|
| 127 | 124 | bool isHSizable () { |
|---|
| 128 | | foreach (d; rowHMin) |
|---|
| 129 | | if (d >= 0) |
|---|
| 130 | | return true; |
|---|
| 131 | | return false; |
|---|
| | 125 | return (sizableRows.length != 0); |
|---|
| 132 | 126 | } |
|---|
| 133 | 127 | |
|---|
| … | … | |
| 140 | 134 | void setSize (int nw, int nh) { |
|---|
| 141 | 135 | // Step 1: calculate the row/column sizes. |
|---|
| 142 | | w += adjustCellSizes (colW, colWMin, nw - w, true); |
|---|
| 143 | | h += adjustCellSizes (rowH, rowHMin, nh - h, true); |
|---|
| 144 | | |
|---|
| 145 | | // Step 2: calculate the row/column offsets (positions) and set the sub-widgets sizes. |
|---|
| | 136 | w += adjustCellSizes (colW, colWMin, sizableCols, nw - w, true); |
|---|
| | 137 | h += adjustCellSizes (rowH, rowHMin, sizableRows, nh - h, true); |
|---|
| | 138 | |
|---|
| | 139 | // Step 2: calculate the row/column offsets (positions) and set the sub-widget's sizes. |
|---|
| 146 | 140 | genCachedMutableData; |
|---|
| 147 | 141 | |
|---|
| … | … | |
| 166 | 160 | int i = cols - 1; // starting from right... |
|---|
| 167 | 161 | while (lx < colX[i]) { // decrement while left of this column |
|---|
| 168 | | assert (i > 0, "getWidget: left of first column"); // should be impossible |
|---|
| | 162 | debug assert (i > 0, "getWidget: left of first column"); // should be impossible |
|---|
| 169 | 163 | --i; |
|---|
| 170 | 164 | } // now (lx >= colX[i]) |
|---|
| … | … | |
| 174 | 168 | int j = rows - 1; |
|---|
| 175 | 169 | while (ly < rowY[j]) { |
|---|
| 176 | | assert (j > 0, "getWidget: above first row"); // should be impossible |
|---|
| | 170 | debug assert (j > 0, "getWidget: above first row"); // should be impossible |
|---|
| 177 | 171 | --j; |
|---|
| 178 | 172 | } |
|---|
| … | … | |
| 191 | 185 | // Resizing columns & rows |
|---|
| 192 | 186 | void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { |
|---|
| | 187 | debug scope (failure) |
|---|
| | 188 | logger.warn ("clickEvent: failure"); |
|---|
| 193 | 189 | if (b == 1 && state == true) { |
|---|
| 194 | | int l = cx - x; // use relative coords |
|---|
| | 190 | /* Note: Because of getWidget, this function is only called if the click is not on a |
|---|
| | 191 | * sub-widget, so we know it's on some divisor (so at least one of resizeCol and |
|---|
| | 192 | * resizeRow is non-negative). */ |
|---|
| 195 | 193 | |
|---|
| 196 | 194 | // Find the column |
|---|
| 197 | | resizeCol = cols - 1; // from the right... |
|---|
| 198 | | while (l < colX[resizeCol]) { // decrement while left of this column |
|---|
| 199 | | assert (resizeCol > 0, "clickEvent: left of first column"); |
|---|
| 200 | | --resizeCol; |
|---|
| 201 | | } // now (l >= colX[resizeCol]) |
|---|
| 202 | | if (l < colX[resizeCol] + colW[resizeCol]) resizeCol = -1; // on a sub-widget |
|---|
| | 195 | if (sizableCols.length != 0) { |
|---|
| | 196 | int l = cx - x; // use relative coords |
|---|
| | 197 | size_t i = cols - 1; // index, from right |
|---|
| | 198 | while (l < colX[i]) { // decrement while left of this column |
|---|
| | 199 | debug assert (i > 0, "clickEvent: left of first column"); |
|---|
| | 200 | --i; |
|---|
| | 201 | } // now (l >= colX[resizeCol]) |
|---|
| | 202 | if (l < colX[i] + colW[i]) i = -1; // on a sub-widget |
|---|
| | 203 | |
|---|
| | 204 | // Set resizeColsL / resizeColsH |
|---|
| | 205 | // Want to find j such that [0..j],[j..$] divide sizableCols about i: |
|---|
| | 206 | size_t j = 0; |
|---|
| | 207 | while (j < sizableCols.length && sizableCols[j] <= i) ++j; |
|---|
| | 208 | |
|---|
| | 209 | resizeColsL = sizableCols[0..j]; |
|---|
| | 210 | resizeColsH = sizableCols[j..$]; |
|---|
| | 211 | |
|---|
| | 212 | // Cannot resize if either list is empty. resizeCallback checks the length of L, |
|---|
| | 213 | // but to save it checking R too, we set L's length zero if R's is. |
|---|
| | 214 | if (resizeColsH.length == 0) |
|---|
| | 215 | resizeColsL = null; |
|---|
| | 216 | } |
|---|
| 203 | 217 | |
|---|
| 204 | 218 | // Find the row |
|---|
| 205 | | resizeRow = rows - 1; |
|---|
| 206 | | while (l < rowY[resizeRow]) { |
|---|
| 207 | | assert (resizeRow > 0, "clickEvent: left of first column"); |
|---|
| 208 | | --resizeRow; |
|---|
| | 219 | if (sizableRows.length != 0) { |
|---|
| | 220 | int l = cy - y; |
|---|
| | 221 | size_t i = rows - 1; |
|---|
| | 222 | while (l < rowY[i]) { |
|---|
| | 223 | debug assert (i > 0, "clickEvent: above first row"); |
|---|
| | 224 | --i; |
|---|
| | 225 | } |
|---|
| | 226 | if (l < rowY[i] + rowH[i]) i = -1; |
|---|
| | 227 | |
|---|
| | 228 | size_t j = 0; |
|---|
| | 229 | while (j < sizableRows.length && sizableRows[j] <= i) ++j; |
|---|
| | 230 | |
|---|
| | 231 | resizeRowsL = sizableRows[0..j]; |
|---|
| | 232 | resizeRowsH = sizableRows[j..$]; |
|---|
| | 233 | |
|---|
| | 234 | if (resizeRowsH.length == 0) |
|---|
| | 235 | resizeRowsL = null; |
|---|
| 209 | 236 | } |
|---|
| 210 | | if (l < rowY[resizeRow] + rowH[resizeRow]) resizeRow = -1; // on a sub-widget |
|---|
| 211 | | |
|---|
| 212 | | /* Note: Because of getWidget, this function is only called if the click is not on a |
|---|
| 213 | | * sub-widget, so we know it's on some divisor (so at least one of resizeCol and |
|---|
| 214 | | * resizeRow is non-negative). */ |
|---|
| | 237 | |
|---|
| | 238 | if (resizeColsL is null && resizeRowsL is null) |
|---|
| | 239 | return; // no resizing to do |
|---|
| 215 | 240 | |
|---|
| 216 | 241 | dragX = cx; |
|---|
| … | … | |
| 261 | 286 | |
|---|
| 262 | 287 | // Find which cols/rows are resizable: |
|---|
| | 288 | sizableCols = sizableRows = null; // reset; we're about to concatenate to them |
|---|
| | 289 | |
|---|
| 263 | 290 | forCols: |
|---|
| 264 | 291 | for (uint i = 0; i < cols; ++i) { // for each column |
|---|
| 265 | 292 | for (uint j = 0; j < subWidgets.length; j += cols) // for each row |
|---|
| 266 | | if (!subWidgets[i+j].isWSizable) { // column not resizable |
|---|
| 267 | | colWMin[i] = -colWMin[i]; // negate to show not resizable |
|---|
| | 293 | if (!subWidgets[i+j].isWSizable) // column not resizable |
|---|
| 268 | 294 | continue forCols; // continue the outer for loop |
|---|
| 269 | | } |
|---|
| 270 | 295 | |
|---|
| 271 | 296 | // column is resizable if we get to here |
|---|
| 272 | | // entry is left positive, meaning it is resizable |
|---|
| | 297 | sizableCols ~= i; |
|---|
| 273 | 298 | } |
|---|
| 274 | 299 | |
|---|
| … | … | |
| 276 | 301 | for (uint i = 0; i < subWidgets.length; i += cols) { // for each row |
|---|
| 277 | 302 | for (uint j = 0; j < cols; ++j) // for each column |
|---|
| 278 | | if (!subWidgets[i+j].isHSizable) { |
|---|
| 279 | | j = i / cols; // reuse: will be reinitialised next iteration |
|---|
| 280 | | rowHMin[j] = -rowHMin[j]; |
|---|
| | 303 | if (!subWidgets[i+j].isHSizable) |
|---|
| 281 | 304 | continue forRows; |
|---|
| 282 | | } |
|---|
| | 305 | |
|---|
| | 306 | sizableRows ~= i / cols; |
|---|
| 283 | 307 | } |
|---|
| 284 | 308 | } |
|---|
| … | … | |
| 315 | 339 | * cellD = current sizes; is adjusted by the function to new sizes |
|---|
| 316 | 340 | * cellDMin = minimal sizes (see colWMin/rowHMin) |
|---|
| | 341 | * sizableCells= List of indexes in cellD for cells which are resizable |
|---|
| 317 | 342 | * diff = amount to increase/decrease the total size |
|---|
| 318 | 343 | * startHigh = if true, start resizing from the tail end of cellD, instead of the beginning |
|---|
| … | … | |
| 321 | 346 | * The amount adjusted. This may be larger than diff, since cellD is clamped by cellDMin. |
|---|
| 322 | 347 | */ |
|---|
| 323 | | int adjustCellSizes (ref int[] cellD, ref int[] cellDMin, int diff, bool startHigh) |
|---|
| | 348 | int adjustCellSizes (ref int[] cellD, ref int[] cellDMin, ref size_t[] sizableCells, int diff, bool startHigh) |
|---|
| 324 | 349 | in {// Could occur if adjust isn't called first, but this would be a code error: |
|---|
| 325 | 350 | assert (cellD !is null, "adjustCellSizes: cellD is null"); |
|---|
| 326 | 351 | } body { |
|---|
| 327 | | size_t i = (startHigh ? cellD.length-1 : 0); |
|---|
| 328 | | size_t ic = (startHigh ? -1 : 1); // amount to iterate to next cell |
|---|
| | 352 | // Cannot resize if no cells are sizable: |
|---|
| | 353 | if (sizableCells.length == 0) return 0; |
|---|
| | 354 | |
|---|
| | 355 | size_t si = (startHigh ? sizableCells.length-1 : 0); // starting index of sizableCells |
|---|
| 329 | 356 | |
|---|
| 330 | 357 | // FIXME: could do with an overhaul |
|---|
| 331 | 358 | if (diff > 0) { // increase size of first resizable cell |
|---|
| 332 | | do { |
|---|
| 333 | | if (cellDMin[i] >= 0) { // cell is resizable |
|---|
| 334 | | cellD[i] += diff; |
|---|
| 335 | | return diff; |
|---|
| 336 | | } |
|---|
| 337 | | i += ic; |
|---|
| 338 | | } while (i >= 0 && i < cellD.length); |
|---|
| 339 | | // no resizable cell: revert to original |
|---|
| 340 | | cellD[(startHigh ? cellD.length-1 : 0)] += diff; |
|---|
| | 359 | cellD[sizableCells[si]] += diff; |
|---|
| 341 | 360 | return diff; |
|---|
| 342 | 361 | } |
|---|
| 343 | 362 | else if (diff < 0) { // decrease |
|---|
| | 363 | size_t sc = (startHigh ? -1 : 1); // amount to iterate |
|---|
| | 364 | size_t ci; // index in cellD |
|---|
| 344 | 365 | int rd = diff; // running diff |
|---|
| 345 | 366 | while (true) { |
|---|
| 346 | | // NOTE: could do this differently so that enlarged cells can be shrunk |
|---|
| 347 | | if (cellDMin[i] >= 0) { // i.e., if resizable: |
|---|
| 348 | | cellD[i] += rd; // decrease this cell's size (but may be too much) |
|---|
| 349 | | rd = cellD[i] - cellDMin[i]; |
|---|
| 350 | | if (rd >= 0) // OK; we're done |
|---|
| 351 | | return diff;// we hit the mark exactly |
|---|
| 352 | | |
|---|
| 353 | | // else we decreased it too much! |
|---|
| 354 | | cellD[i] = cellDMin[i]; |
|---|
| 355 | | // rd is remainder to decrease by |
|---|
| 356 | | } |
|---|
| 357 | | |
|---|
| 358 | | i += (startHigh ? -1 : 1); // next cell |
|---|
| 359 | | if (i < 0 || i >= cellD.length) // run out of next cells |
|---|
| 360 | | return diff - rd; // still had rd left to decrease |
|---|
| | 367 | ci = sizableCells[si]; |
|---|
| | 368 | |
|---|
| | 369 | cellD[ci] += rd; // decrease this cell's size (but may be too much) |
|---|
| | 370 | rd = cellD[ci] - cellDMin[ci]; |
|---|
| | 371 | if (rd >= 0) // OK; we're done |
|---|
| | 372 | return diff;// we hit the mark exactly |
|---|
| | 373 | |
|---|
| | 374 | // else we decreased it too much! |
|---|
| | 375 | cellD[ci] = cellDMin[ci]; |
|---|
| | 376 | // rd is remainder to decrease by |
|---|
| | 377 | |
|---|
| | 378 | si += sc; // iterate |
|---|
| | 379 | if (si < 0 || si >= sizableCells.length) // run out of next cells |
|---|
| | 380 | return diff - rd; // still had rd left to decrease |
|---|
| 361 | 381 | } |
|---|
| 362 | 382 | } |
|---|
| … | … | |
| 369 | 389 | int move; // NOTE: all resizing is relative, unlike in Window |
|---|
| 370 | 390 | |
|---|
| 371 | | if (resizeCol >= 0) { |
|---|
| | 391 | if (resizeColsL.length != 0) { |
|---|
| 372 | 392 | move = cx - dragX; |
|---|
| 373 | | int[] d0 = colW[0..resizeCol]; |
|---|
| 374 | | int[] d1 = colW[resizeCol..$]; |
|---|
| 375 | | int[] m0 = colWMin[0..resizeCol]; |
|---|
| 376 | | int[] m1 = colWMin[resizeCol..$]; |
|---|
| 377 | 393 | |
|---|
| 378 | 394 | // do shrinking first (in case we hit the minimum) |
|---|
| 379 | 395 | // Note: we rely on x[a..b] pointing to the same memory as x |
|---|
| 380 | | if (move > 0) { |
|---|
| 381 | | move = -adjustCellSizes (d1, m1, -move, false); |
|---|
| 382 | | adjustCellSizes (d0, m0, move, true); |
|---|
| | 396 | if (move < 0) { |
|---|
| | 397 | move = -adjustCellSizes (colW, colWMin, resizeColsL, move, false); |
|---|
| | 398 | adjustCellSizes (colW, colWMin, resizeColsH, move, true); |
|---|
| 383 | 399 | } else { |
|---|
| 384 | | move = -adjustCellSizes (d0, m0, move, true); |
|---|
| 385 | | adjustCellSizes (d1, m1, move, false); |
|---|
| | 400 | move = -adjustCellSizes (colW, colWMin, resizeColsH, -move, true); |
|---|
| | 401 | adjustCellSizes (colW, colWMin, resizeColsL, move, false); |
|---|
| 386 | 402 | } |
|---|
| 387 | | } |
|---|
| 388 | | // FIXME: vertical |
|---|
| 389 | | |
|---|
| | 403 | |
|---|
| | 404 | dragX = cx; |
|---|
| | 405 | } |
|---|
| | 406 | |
|---|
| | 407 | if (resizeRowsL.length != 0) { |
|---|
| | 408 | move = cy - dragY; |
|---|
| | 409 | |
|---|
| | 410 | // do shrinking first (in case we hit the minimum) |
|---|
| | 411 | // Note: we rely on x[a..b] pointing to the same memory as x |
|---|
| | 412 | if (move < 0) { |
|---|
| | 413 | move = -adjustCellSizes (rowH, rowHMin, resizeRowsL, move, false); |
|---|
| | 414 | adjustCellSizes (rowH, rowHMin, resizeRowsH, move, true); |
|---|
| | 415 | } else { |
|---|
| | 416 | move = -adjustCellSizes (rowH, rowHMin, resizeRowsH, -move, true); |
|---|
| | 417 | adjustCellSizes (rowH, rowHMin, resizeRowsL, move, false); |
|---|
| | 418 | } |
|---|
| | 419 | |
|---|
| | 420 | dragY = cy; |
|---|
| | 421 | } |
|---|
| | 422 | |
|---|
| | 423 | // NOTE: this might be able to be made more efficient, but basically this all needs to happen: |
|---|
| | 424 | genCachedMutableData; |
|---|
| | 425 | setPosition (x,y); |
|---|
| 390 | 426 | window.requestRedraw; |
|---|
| 391 | 427 | } |
|---|
| … | … | |
| 393 | 429 | if (b == 1 && state == false) { |
|---|
| 394 | 430 | window.gui.removeCallbacks (cast(void*) this); |
|---|
| | 431 | // Remove unwanted data (although it shouldn't free any memory): |
|---|
| | 432 | resizeColsL = resizeColsH = resizeRowsL = resizeRowsH = null; |
|---|
| 395 | 433 | return true; // we've handled the up-click |
|---|
| 396 | 434 | } |
|---|
| … | … | |
| 400 | 438 | protected: |
|---|
| 401 | 439 | // Data for resizing cols/rows: |
|---|
| 402 | | int resizeCol = -1, // col/row being resized; |
|---|
| 403 | | resizeRow = -1; // negative if none |
|---|
| 404 | 440 | int dragX, dragY; // coords where drag starts |
|---|
| | 441 | // Lists of columns/rows with lower/higher index than the resize position |
|---|
| | 442 | size_t[] resizeColsL, resizeColsH, resizeRowsL, resizeRowsH; |
|---|
| 405 | 443 | //END Col/row resizing |
|---|
| 406 | 444 | |
|---|
| 407 | | // Construction data (saved): |
|---|
| | 445 | |
|---|
| | 446 | //BEGIN Construction (i.e. non-mutable) data |
|---|
| 408 | 447 | int cols, rows; // number of cells in grid |
|---|
| 409 | | IWidget[] subWidgets; // all widgets in the grid (by row): |
|---|
| 410 | | /* SubWidget order: [ 0 1 ] |
|---|
| 411 | | * [ 2 3 ] */ |
|---|
| | 448 | |
|---|
| | 449 | /* All widgets in the grid, by row. Order: [ 0 1 ] |
|---|
| | 450 | * [ 2 3 ] */ |
|---|
| | 451 | IWidget[] subWidgets; |
|---|
| 412 | 452 | |
|---|
| 413 | 453 | // Cached data calculated from construction data: |
|---|
| 414 | | int[] colWMin; // absolute value is minimal column width / row height |
|---|
| 415 | | int[] rowHMin; // negative if fixed size, entry >= 0 if resizible |
|---|
| | 454 | // Minimal column width / row height: |
|---|
| | 455 | int[] colWMin, rowHMin; |
|---|
| 416 | 456 | int mw, mh; // minimal dimensions |
|---|
| 417 | 457 | |
|---|
| 418 | | // Mutable data (saved): |
|---|
| 419 | | int[] colW; // column width (widest widget) |
|---|
| 420 | | int[] rowH; // row height (highest widget in the row) |
|---|
| | 458 | // All resizable cols/rows, in order: |
|---|
| | 459 | size_t[] sizableCols, sizableRows; |
|---|
| | 460 | //END Construction data |
|---|
| | 461 | |
|---|
| | 462 | |
|---|
| | 463 | //BEGIN Mutable data |
|---|
| | 464 | int[] colW, rowH; // column width / row height (largest size in col/row) |
|---|
| 421 | 465 | |
|---|
| 422 | 466 | // Cached data calculated from construction and mutable data: |
|---|
| 423 | | int[] colX; // cumulative colW[i-1] + padding (add x to get column's left x-coord) |
|---|
| 424 | | int[] rowY; // cumulative rowH[i-1] + padding |
|---|
| | 467 | int[] colX, rowY; // cumulative colW[i-1] + padding (add x to get column's left x-coord) |
|---|
| | 468 | //END Mutable data |
|---|
| 425 | 469 | } |
|---|
| r36 |
r43 |
|
| 55 | 55 | } |
|---|
| 56 | 56 | |
|---|
| 57 | | if (miscOpts.pollInterval !<= 0.1 || miscOpts.pollInterval !>= 0.0) |
|---|
| 58 | | Options.setDouble ("misc", "pollInterval", 0.0); |
|---|
| | 57 | if (miscOpts.pollInterval !<= 1.0 || miscOpts.pollInterval !>= 0.0) |
|---|
| | 58 | Options.setDouble ("misc", "pollInterval", 0.01); |
|---|
| 59 | 59 | //END Initialisation |
|---|
| 60 | 60 | |
|---|
| r32 |
r43 |
|
| 140 | 140 | } |
|---|
| 141 | 141 | |
|---|
| 142 | | // Now re-set the logging level: |
|---|
| 143 | | Log.getRootLogger.setLevel (cast(Log.Level) miscOpts.logLevel, true); // set the stored log level |
|---|
| | 142 | // Now re-set the logging level, using the value from the config file: |
|---|
| | 143 | Log.getRootLogger.setLevel (cast(Log.Level) miscOpts.logLevel, true); |
|---|
| | 144 | // And set this (debug option): |
|---|
| | 145 | imde.run = !miscOpts.exitImmediately; |
|---|
| 144 | 146 | //END Pre-init |
|---|
| 145 | 147 | |
|---|