Changeset 46:03fa79a48c48

Show
Ignore:
Timestamp:
05/22/08 07:51:47 (8 months ago)
Author:
Diggory Hardy <diggory.hardy@gmail.com>
branch:
default
convert_revision:
d236a4b6f8282486ec25fa9569920085f7cc21b7
Message:

Fixed resizing bugs in previous commit and made code cleaner and more efficient.

setSize replaced by setWidth & setHeight.
setPosition must be called after setWidth/Height.

committer: Diggory Hardy <diggory.hardy@gmail.com>

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • codeDoc/jobs.txt

    r45 r46  
    5757 
    5858Done (for git log message): 
    59 Moved the implementable widgets from mde.gui.widget.Widget to miscWidgets, leaving base widgets in Widget. 
    60 Rewrote some of GridLayoutWidget's implementation. Made many operations general to work for either columns or rows. Some optimisations were intended but ended up being removed due to problems. 
    61 Allowed layout's to resize from either direction (only with window resizes). 
  • data/conf/gui.mtt

    r45 r46  
    1212<int|x=20> 
    1313<int|y=100> 
    14 <int[][int]|widgetData=[1:[0x4010,50,50],2:[0xB004,3,1,3,1,3],3:[0x3001],0:[0xB004,3,1,3,1,3]]> 
     14<int[][int]|widgetData=[1:[0x4010,50,50],2:[0xB004,3,1,3,1,3],3:[0x3001],0:[0xB004,3,1,2,1,2]]> 
  • mde/gui/widget/Ifaces.d

    r45 r46  
    2222/** Interface for Window, allowing widgets to call some of Window's methods. 
    2323 * 
    24  * Contains the methods in Window available for widgets to call on their root. */ 
     24 * Contains the methods in Window available for widgets to call on their root. 
     25 * 
     26 * Notation: 
     27 *  Positive/negative direction: along the x/y axis in this direction. 
     28 *  Layout widget: a widget containing multiple sub-widges (which hence controls how they are laid 
     29 *  out). */ 
    2530interface IWindow : IWidget 
    2631{ 
     
    120125    /** Used to adjust the size. 
    121126     * 
    122      * w,h is the new size. The boolean parameters describe which direction to resize from and is 
    123      * only really relevent to layout widgets (see GridLayoutWidget's implementation). When 
    124      * calling, just past true,true if it doesn't matter. 
     127     * Params: 
     128     *  nw/nh   = The new width/height 
     129     *  dir = Direction to resize from. This is only really applicable to layout widgets. 
     130     *        It must be either -1 (start resizing from highest row/col index, decreasing the 
     131     *        index as necessary), or +1 (resize from the lowest index, i.e. 0). 
     132     *        Most widgets can simply ignore it. 
    125133     * 
    126134     * Implementation: 
     
    131139     * to fill a whole row/column in a layout widget. 
    132140     * 
    133      * If the actual size is needed, call getCurrentSize afterwards. */ 
    134     void setSize (int w, int h, bool, bool); 
     141     * If the actual size is needed, call getCurrentSize afterwards. setPosition must be called 
     142     * afterwards if the widget might be a layout widget. */ 
     143    void setWidth (int nw, int dir); 
     144    void setHeight (int nh, int dir);   /// ditto 
    135145     
    136146    /** Set the current position (i.e. called on init and move). */ 
  • mde/gui/widget/Widget.d

    r45 r46  
    4141    // still need to set their size. 
    4242    int[] adjust (int[] data) { 
    43         setSize (0,0,true,true); 
     43        setWidth (0,-1); 
     44        setHeight (0,-1); 
    4445        return data; 
    4546    } 
     
    7374    /* Set size: minimal size is (mw,mh). Note that both resizable and fixed widgets should allow 
    7475     * enlarging, so in both cases this is a correct implementation. */ 
    75     void setSize (int nw, int nh, bool, bool) { 
     76    void setWidth (int nw, int) { 
    7677        w = (nw >= mw ? nw : mw); 
     78    } 
     79    void setHeight (int nh, int) { 
    7780        h = (nh >= mh ? nh : mh); 
    7881    } 
  • mde/gui/widget/Window.d

    r45 r46  
    8686        widgetY = y + border.t;         // must be updated if the window is moved 
    8787        widget.setPosition (widgetX, widgetY); 
     88         
     89        // Calculate mw/mh and xw/yh (cached data): 
     90        widget.getMinimalSize (mw, mh); 
     91        mw += border.l + border.r; 
     92        mh += border.t + border.b; 
    8893         
    8994        xw = x+w; 
     
    207212     
    208213    void getMinimalSize (out int wM, out int hM) { 
    209         if (mh < 0) {       // calculate if necessary 
    210             widget.getMinimalSize (mw, mh); 
    211             mw += border.l + border.r; 
    212             mh += border.t + border.b; 
    213         } 
     214        // mw/mh are calculated by finalise(); 
    214215        wM = mw; 
    215216        hM = mh; 
     
    220221    } 
    221222     
    222     void setSize (int nw, int nh, bool wB, bool hB) { 
    223         getMinimalSize (w,h); 
    224         if (nw > w) w = nw;     // expand if new size is larger, but don't go smaller 
    225         if (nh > h) h = nh
    226          
    227         xw = x+w; 
    228         yh = y+h; 
    229          
    230         widget.setSize (w - border.l - border.r, h - border.t - border.b, wB, hB)
    231          
    232         gui_.requestRedraw ();  // obviously necessary whenever the window's size is changed 
     223    void setWidth (int nw, int dir) { 
     224        if (nw < mw) w = mw;   // clamp 
     225        else w = nw; 
     226        xw = x + w
     227        widget.setWidth (w - border.l - border.r, dir); 
     228    } 
     229    void setHeight (int nh, int dir) { 
     230        if (nh < mh) h = mh;   // clamp 
     231        else h = nh
     232        yh = y + h; 
     233        widget.setHeight (h - border.t - border.b, dir); 
    233234    } 
    234235     
     
    245246        widget.setPosition (widgetX, widgetY); 
    246247         
    247         gui_.requestRedraw ();  // obviously necessary whenever the window is moved 
     248        gui_.requestRedraw ();  // necessary whenever the window is moved; setPosition is called after resizes and moves 
    248249    } 
    249250     
     
    308309         
    309310        // This function is only called if some resize is going to happen. 
    310         // To improve efficiency, store parameters to resize to. 
    311         int xSize = w, ySize = h;   // new size 
    312         int xDiff, yDiff;       // difference to new position 
    313         bool xHigh, yHigh;      // resize from positive side 
     311        // x,y are used as parameters to setPosition as well as being affected by it; somewhat 
     312        // pointless but fairly effective. 
    314313         
    315314        if (resizeType & RESIZE_TYPE.L) { 
    316             getMinimalSize (xDiff, xSize); // (only want xDiff, temporarily used as mw) 
    317             xSize = xDrag - cx; 
    318             if (xSize < xDiff) xSize = xDiff;  // clamp 
    319             xDiff = w - xSize;         // now used as amount to move 
     315            int xSize = xDrag - cx; 
     316            if (xSize < mw) xSize = mw;    // clamp 
     317            x += w - xSize; 
     318            setWidth (xSize, 1); 
    320319        } 
    321320        else if (resizeType & RESIZE_TYPE.R) { 
    322             xSize = xDrag + cx; 
    323             xHigh = true; 
     321            setWidth (xDrag + cx, -1); 
    324322        } 
    325323        if (resizeType & RESIZE_TYPE.T) { 
    326             getMinimalSize (ySize, yDiff)
    327             ySize = yDrag - cy
    328             if (ySize < yDiff) ySize = yDiff
    329             yDiff = h - ySize
     324            int ySize = yDrag - cy
     325            if (ySize < mh) ySize = mh
     326            y += h - ySize
     327            setHeight (ySize, 1)
    330328        } 
    331329        else if (resizeType & RESIZE_TYPE.B) { 
    332             ySize = yDrag + cy; 
    333             yHigh = true; 
    334         } 
    335          
    336         setSize (xSize, ySize, xHigh, yHigh); 
    337         if (xDiff != 0 || yDiff != 0) 
    338             setPosition (x + xDiff, y + yDiff); 
     330            setHeight (yDrag + cy, -1); 
     331        } 
     332         
     333        // Moves lower (x,y) coordinate if necessary and repositions any sub-widgets moved by the 
     334        // resizing: 
     335        setPosition (x, y); 
    339336    } 
    340337    bool endCallback (ushort cx, ushort cy, ubyte b, bool state) { 
  • mde/gui/widget/layout.d

    r45 r46  
    3838class GridLayoutWidget : Widget 
    3939{ 
     40    //BEGIN Creation & saving 
    4041    this (IWindow wind, int[] data) { 
    4142        // Get grid size and check data 
     
    6364    } 
    6465     
     66    /* This does two things: 
     67     * 1. Pass adjust data on to sub-widgets 
     68     * 2. Set the size, from the adjust data if possible 
     69     */ 
    6570    int[] adjust (int[] data) { 
    6671        // Give all sub-widgets their data: 
     
    9095         
    9196        // Tell subwidgets their new sizes. Positions are given by a later call to setPosition. 
    92         foreach (i,widget; subWidgets) 
    93             // Resizing direction is arbitrarily set to "high direction": 
    94             widget.setSize (col.width[i % cols], row.width[i / cols], true, true); 
     97        foreach (i,widget; subWidgets) { 
     98            // Resizing direction is arbitrarily set to negative: 
     99            widget.setWidth  (col.width[i % cols], -1); 
     100            widget.setHeight (row.width[i / cols], -1); 
     101        } 
    95102         
    96103        return data[lenUsed..$]; 
     
    116123        return ret; 
    117124    } 
    118      
     125    //END Creation & saving 
     126     
     127    //BEGIN Size & position 
    119128    bool isWSizable () { 
    120129        return col.firstSizable >= 0; 
     
    130139    } 
    131140     
    132     void setSize (int nw, int nh, bool wHigh, bool hHigh) { 
    133         debug scope (failure) { 
    134             char[128] tmp; 
    135                 logger.trace ("setSize failed: hHigh = " ~ (hHigh ? "true" : "false")); 
    136                 logger.trace (logger.format (tmp, "rows to resize: {}, {}", row.firstSizable, row.lastSizable)); 
    137         } 
    138         // Optimisation (could easily be called with same sizes if a parent layout widget is 
    139         // resized, since many columns/rows may not be resized). 
    140         if (nw == w && nh == h) return; 
    141          
    142         // calculate the row/column sizes (and new positions) 
    143         if (wHigh) 
    144             w += col.adjustCellSizes (nw - w, col.lastSizable, -1); 
    145         else 
    146             w += col.adjustCellSizes (nw - w, col.firstSizable, 1); 
    147         if (hHigh) 
    148             h += row.adjustCellSizes (nh - h, row.lastSizable, -1); 
    149         else 
    150             h += row.adjustCellSizes (nh - h, row.firstSizable, 1); 
    151          
    152         // set the sub-widget's sizes & positions 
    153         setSubWidgetSP (wHigh, hHigh); 
     141    void setWidth (int nw, int dir) { 
     142        if (nw == w) return; 
     143         
     144        w += col.adjustCellSizes (nw - w, (dir == -1 ? col.lastSizable : col.firstSizable), dir); 
     145         
     146        // Note: setPosition must be called after! 
     147    } 
     148    void setHeight (int nh, int dir) { 
     149        if (nh == h) return; 
     150         
     151        h += row.adjustCellSizes (nh - h, (dir == -1 ? row.lastSizable : row.firstSizable), dir); 
     152         
     153        // Note: setPosition must be called after! 
    154154    } 
    155155     
     
    161161            widget.setPosition (x + col.pos[i % cols], y + row.pos[i / cols]); 
    162162    } 
     163    //END Size & position 
    163164     
    164165     
     
    211212    void genCachedConstructionData () { 
    212213        col.spacing = row.spacing = window.renderer.layoutSpacing; 
     214        col.setColWidth = &setColWidth; 
     215        row.setColWidth = &setRowHeight; 
    213216         
    214217        // Calculate the minimal column and row sizes: 
     
    270273        } 
    271274    } 
    272      
    273     // set sub-widgets size & position (done after resizing widget or rows/columns) 
    274     void setSubWidgetSP (bool wH, bool hH) { 
    275         for (myIt i = 0; i < cols; ++i) 
    276             for (myIt j = 0; j < rows; ++j) 
    277         { 
    278             IWidget widget = subWidgets[i + cols*j]; 
    279             widget.setSize (col.width[i], row.width[j], wH, hH); 
    280             widget.setPosition (x + col.pos[i], y + row.pos[j]); 
    281         } 
    282     } 
    283275    //END Cache calculation functions 
    284276     
    285277     
    286     //BEGIN Col/row resizing 
     278    void setColWidth (myIt i, int w, int dir) { 
     279        for (myIt j = 0; j < rows; ++j) { 
     280            subWidgets[i + cols*j].setWidth (w, dir); 
     281        } 
     282    } 
     283    void setRowHeight (myIt j, int h, int dir) { 
     284        for (myIt i = 0; i < cols; ++i) { 
     285            subWidgets[i + cols*j].setHeight (h, dir); 
     286        } 
     287    } 
     288     
     289     
     290    //BEGIN Col/row resizing callback 
    287291    void resizeCallback (ushort cx, ushort cy) { 
    288292        col.resize (cx - dragX); 
     
    293297        dragY = cy; 
    294298         
    295         // NOTE: Resizing direction is set to "high direction" which isn't always going to be 
    296         // correct. A more accurate but more complex approach might be to get 
    297         // adjustCellSizes to do the work. 
    298         setSubWidgetSP (true, true); 
     299        foreach (i,widget; subWidgets) 
     300            widget.setPosition (x + col.pos[i % cols], 
     301                                y + row.pos[i / cols]); 
    299302        window.requestRedraw; 
    300303    } 
     
    310313    // Data for resizing cols/rows: 
    311314    int dragX, dragY;   // coords where drag starts 
    312     //END Col/row resizing 
     315    //END Col/row resizing callback 
    313316     
    314317     
     
    335338               resizeU; // and up from this index 
    336339        int spacing;    // used by genPositions (which cannot access the layout class's data) 
     340        /* This is a delegate to a enclosing class's function, since: 
     341         * a different implementation is needed for cols or rows 
     342         * we're unable to access enclosing class members directly */ 
     343        void delegate (myIt,int,int) setColWidth;   // set width of a column, with resize direction 
    337344         
    338345        void dupMin () { 
     
    408415        * Returns: 
    409416        *  The amount adjusted. This may be larger than diff, since cellD is clamped by cellDMin. 
     417        * 
     418        * Note: Check variable used for start is valid before calling! If a non-sizable column's 
     419        *  index is passed, this should get increased (if diff > 0) but not decreased. 
    410420        */ 
    411         int adjustCellSizes (int diff, myDiff start, myDiff incr) 
    412         in {// Could occur if adjust isn't called first, but this would be a code error: 
    413             char[128] tmp; 
    414             logger.trace (logger.format (tmp, "start is {}", start)); 
     421        int adjustCellSizes (int diff, myDiff start, int incr) 
     422        in { 
     423            // Could occur if adjust isn't called first, but this would be a code error: 
    415424            assert (width !is null, "adjustCellSizes: width is null"); 
     425            // Most likely if passed negative when sizing is disabled: 
    416426            assert (start >= 0 && start < minWidth.length, "adjustCellSizes: invalid start"); 
    417427            assert (incr == 1 || incr == -1, "adjustCellSizes: invalid incr"); 
     428            assert (setColWidth !is null, "adjustCellSizes: setColWidth is null"); 
    418429        } body { 
    419430            debug scope(failure) 
     
    422433            if (diff > 0) {     // increase size of first resizable cell 
    423434                width[i] += diff; 
     435                setColWidth (i, width[i], incr); 
    424436            } 
    425437            else if (diff < 0) {    // decrease 
     
    429441                    width[i] += rd; // decrease this cell's size (but may be too much) 
    430442                    rd = width[i] - minWidth[i]; 
    431                     if (rd >= 0)    // OK; we're done 
     443                    if (rd >= 0) {  // OK; we're done 
     444                        setColWidth (i, width[i], incr);    // set new width 
    432445                        break;      // we hit the mark exactly: diff is correct 
     446                    } 
    433447                     
    434448                    // else we decreased it too much! 
    435449                    width[i] = minWidth[i]; 
     450                    setColWidth (i, width[i], incr); 
    436451                    // rd is remainder to decrease by 
     452                     
    437453                     
    438454                    bool it = true; // iterate (force first time) 
     
    469485     
    470486    // Index types. Note that in some cases they need to hold negative values. 
     487    // Int is used for resizing direction (although ptrdiff_t would be more appropriate), 
     488    // since the value must always be -1 or +1 and int is smaller on X86_64. 
    471489    alias size_t myIt; 
    472490    alias ptrdiff_t myDiff;