Changeset 41:b3a6ca4516b4

Show
Ignore:
Timestamp:
05/13/08 07:02:36 (8 months ago)
Author:
Diggory Hardy <diggory.hardy@gmail.com>
branch:
default
convert_revision:
0baf1014719a3f84a263957add17e6372d16badb
Message:

The renderer now controls which parts of the window border allow resizing.

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

Files:

Legend:

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

    r40 r41  
    44 
    55In progress: 
    6 Make a widget with multiple sizable rows/cols. 
    76Implement row/col sizing. 
    87 
     
    5150 
    5251Done (for git log message): 
     52The renderer now controls which parts of the window border allow resizing. 
  • mde/gui/Gui.d

    r39 r41  
    2525import mde.gui.widget.Ifaces; 
    2626import mde.gui.widget.Window; 
    27 import mde.gui.renderer.createRenderer; 
    2827import mde.gui.exception; 
    2928 
     
    8584        } 
    8685        rendName = *p; 
    87         rend = createRenderer (rendName); 
    8886         
    8987        // get list 
     
    150148        // NOTE: buttons receive the up-event even when drag-callbacks are in place. 
    151149        foreach (dg; clickCallbacks) 
    152             dg (cx, cy, b, state); 
     150            if (dg (cx, cy, b, state)) return;      // See IGui.addClickCallback's documentation 
    153151         
    154152        foreach (i,w; windows) { 
     
    175173     
    176174    //BEGIN IGui methods 
    177     IRenderer renderer () 
    178     in { 
    179         assert (rend !is null, "Gui: rend is null"); 
    180     } body { 
    181         return rend; 
     175    char[] rendererName () { 
     176        return rendName; 
    182177    } 
    183178     
     
    186181    } 
    187182     
    188     void addClickCallback (void delegate(ushort, ushort, ubyte, bool) dg) { 
     183    void addClickCallback (bool delegate(ushort, ushort, ubyte, bool) dg) { 
    189184        clickCallbacks[dg.ptr] = dg; 
    190185    } 
     
    201196    Window[] windows;   // Windows. First window is "on top", others may be obscured. 
    202197     
    203     IRenderer rend;     // Renderer (synonymous with theme) 
    204     char[] rendName;    // Name of renderer; for saving 
     198    char[] rendName;    // Name of renderer; for saving and creating renderers 
    205199     
    206200    // callbacks indexed by their frame pointers: 
    207     void delegate(ushort cx, ushort cy, ubyte b, bool state) [void*] clickCallbacks; 
     201    bool delegate(ushort cx, ushort cy, ubyte b, bool state) [void*] clickCallbacks; 
    208202    void delegate(ushort cx, ushort cy) [void*] motionCallbacks; 
    209203} 
  • mde/gui/IGui.d

    r36 r41  
    1616module mde.gui.IGui; 
    1717 
    18 public import mde.gui.renderer.IRenderer; 
    19  
    2018/** The Gui interface. 
    2119* 
     
    2422interface IGui 
    2523{ 
    26     /** Get the Gui's renderer. May be overriden by the window. */ 
    27     IRenderer renderer (); 
     24    /** Get the GUI's rendererName for creating a renderer (may be overridden by the window). */ 
     25    char[] rendererName (); 
    2826     
    2927    /** Called by a sub-widget when a redraw is necessary (since drawing may sometimes be done on 
     
    3331    void requestRedraw (); 
    3432     
    35     /** Add a mouse click callback: delegate will be called for all mouse click events recieved. */ 
    36     void addClickCallback (void delegate (ushort cx, ushort cy, ubyte b, bool state) dg); 
     33    /** Add a mouse click callback: delegate will be called for all mouse click events recieved. 
     34     * 
     35     * The delegate should return true if it accepts the event and no further processing is 
     36     * required (i.e. the event should not be handled by anything else), false otherwise. 
     37     * Note that this is not a mechanism to prevent unwanted event handling, and in the future may 
     38     * be removed (so event handling cannot be cut short). */ 
     39    void addClickCallback (bool delegate (ushort cx, ushort cy, ubyte b, bool state) dg); 
    3740    /** Add a mouse motion callback: delegate will be called for all motion events recieved. */ 
    3841    void addMotionCallback (void delegate (ushort cx, ushort cy) dg); 
  • mde/gui/renderer/IRenderer.d

    r38 r41  
    4040    } 
    4141     
    42     /// An enum for border types 
    43     enum BORDER_TYPES { 
    44         WINDOW_TOTAL, 
    45         WINDOW_RESIZE, 
     42    /** Use to set and reset these parameters, and to get the border size (which may depend on 
     43     * them). */ 
     44    BorderDimensions setSizable (bool wSizable, bool hSizable); 
     45     
     46    /// Which edges of a window are being resized 
     47    enum RESIZE_TYPE : ubyte { 
     48        NONE = 0x0, L = 0x1, R = 0x2, T = 0x4, B = 0x8 
    4649    } 
    4750     
    48     /** Return the renderer's window border width. 
    49      * 
    50      * Type should be an element of BORDER_TYPES; if not the method may throw or simply return 
    51      * without an error. */ 
    52     BorderDimensions getBorder (BORDER_TYPES type); 
     51    /** Used to tell if a click on a window's border is for resizing or moving. 
     52    * 
     53    * Depends on setSizable's parameters. 
     54    * 
     55    * Params: 
     56    *   cx = 
     57    *   cy = click coordinates relative to window border 
     58    *   w  = 
     59    *   h  = window size 
     60    * 
     61    * Returns: 
     62    *   RESIZE_TYPE = NONE for a move, an or'd combination of L/R/T/B for resizing. 
     63    */ 
     64    RESIZE_TYPE getResizeType (int cx, int cy, int w, int h); 
    5365     
    5466    /** Return the renderer's between-widget spacing (for layout widgets). */ 
  • mde/gui/renderer/SimpleRenderer.d

    r39 r41  
    3030class SimpleRenderer : IRenderer 
    3131{ 
    32     BorderDimensions getBorder (BORDER_TYPES type) { 
    33         BorderDimensions dims; 
    34         with (BORDER_TYPES) with (dims) { 
    35             if (type == WINDOW_TOTAL) { 
    36                 l = t = r = b = 20; 
    37             } else if (type == WINDOW_RESIZE) { 
    38                 r = t = 5; 
    39                 l = b = 20; 
     32    BorderDimensions setSizable (bool wS, bool hS) { 
     33        wSizable = wS; 
     34        hSizable = hS; 
     35         
     36        // Set the border size based on the above 
     37        with (border) { 
     38            l = r = t = b = 14; 
     39        } 
     40        with (resize) { 
     41            if (wSizable) 
     42                l = r = 6; 
     43            else 
     44                l = r = 0; 
     45            if (hSizable) { 
     46                t = 2; 
     47                b = 6; 
     48            } else 
     49                t = b = 0; 
     50        } 
     51        border += resize; 
     52        return border; 
     53    } 
     54     
     55    RESIZE_TYPE getResizeType (int cx, int cy, int w, int h) { 
     56        RESIZE_TYPE resizeType = RESIZE_TYPE.NONE; 
     57        if (cx < resize.l || cx >= w - resize.r || 
     58            cy < resize.t || cy >= h - resize.b) { // window is being resized 
     59                /* check for resizes (different to above; use whole border giving larger area for 
     60                * diagonal resizes). */ 
     61             
     62            if (wSizable) { 
     63                if (cx < border.l) 
     64                    resizeType = RESIZE_TYPE.L; 
     65                else if (cx >= w - border.r) 
     66                    resizeType = RESIZE_TYPE.R; 
     67            } 
     68            if (hSizable) { 
     69                if (cy < border.t) 
     70                    resizeType |= RESIZE_TYPE.T; 
     71                else if (cy >= h - border.b) 
     72                    resizeType |= RESIZE_TYPE.B; 
    4073            } 
    4174        } 
    42         return dims
     75        return resizeType
    4376    } 
    4477     
     
    5386         
    5487        gl.setColor (0f, 0f, 1f); 
    55         gl.drawBox (x+20,y+5, w-25,h-25); 
     88        gl.drawBox (x+resize.l, y+resize.t, w-resize.l-resize.r, h-resize.t-resize.b); 
    5689         
    5790        gl.setColor (.3f, .3f, .3f); 
    58         gl.drawBox (x+20, y+20, w-40, h-40); 
     91        gl.drawBox (x+border.l, y+border.t, w-border.l-border.r, h-border.t-border.b); 
    5992    } 
    6093 
     
    68101        gl.drawBox (x,y, w,h); 
    69102    } 
     103     
     104protected: 
     105    bool wSizable, hSizable; 
     106    BorderDimensions border; 
     107    BorderDimensions resize; 
    70108} 
  • mde/gui/widget/Ifaces.d

    r40 r41  
    3939    widgetID addCreationData (IWidget widget); 
    4040     
    41     /** Get the managing Gui. */ 
    42     //FIXME: remove and add requestRedraw to allow for only redrawing the window 
     41    /** Returns the window's gui. */ 
     42    //NOTE: was going to remove this, but it's used more than I thought 
    4343    IGui gui (); 
     44     
     45    /** The widget/window needs redrawing. */ 
     46    void requestRedraw (); 
    4447     
    4548    /** Get the window's renderer. 
  • mde/gui/widget/Widget.d

    r39 r41  
    1818 
    1919public import mde.gui.widget.Ifaces; 
    20 import mde.gui.IGui; 
    2120import mde.gui.exception; 
     21import mde.gui.renderer.IRenderer; 
    2222 
    2323import tango.io.Stdout; 
     
    169169        if (b == 1 && state == true) { 
    170170            pushed = true; 
    171             window.gui.requestRedraw; 
     171            window.requestRedraw; 
    172172            window.gui.addClickCallback (&clickWhileHeld); 
    173173            window.gui.addMotionCallback (&motionWhileHeld); 
     
    175175    } 
    176176    // Called when a mouse motion/click event occurs while (held == true) 
    177     void clickWhileHeld (ushort cx, ushort cy, ubyte b, bool state) { 
     177    bool clickWhileHeld (ushort cx, ushort cy, ubyte b, bool state) { 
     178        //NOTE: which button? test 
    178179        if (cx >= x && cx < x+w && cy >= y && cy < y+h) // button event 
    179180            Stdout ("Button clicked!").newline; 
    180181         
    181182        pushed = false; 
    182         window.gui.requestRedraw; 
     183        window.requestRedraw; 
    183184        window.gui.removeCallbacks (cast(void*) this); 
     185         
     186        return false; 
    184187    } 
    185188    void motionWhileHeld (ushort cx, ushort cy) { 
     
    188191        else pushed = false; 
    189192        if (oldPushed != pushed) 
    190             window.gui.requestRedraw; 
     193            window.requestRedraw; 
    191194    } 
    192195} 
  • mde/gui/widget/Window.d

    r40 r41  
    2323import mde.gui.IGui; 
    2424import mde.gui.exception; 
     25import mde.gui.renderer.createRenderer; 
    2526 
    2627import mt = mde.mergetag.DataSet; 
     
    6263            throw new WindowLoadException ("No widget creation data"); 
    6364         
     65        // Save gui and create the renderer: 
    6466        gui_ = gui; 
    65         rend = gui.renderer; 
    66          
    67         // Get border sizes 
    68         border = rend.getBorder (BORDER_TYPES.WINDOW_TOTAL); 
    69         resize = rend.getBorder (BORDER_TYPES.WINDOW_RESIZE); 
     67        rend = createRenderer (gui.rendererName); 
    7068         
    7169        // Create the primary widget (and indirectly all sub-widgets), throwing on error: 
    72         widget = makeWidget (0);    // primary widget always has ID 0. 
     70        // Note: GridLayoutWidget's this relies on rend.layoutSpacing. 
     71        widget = makeWidget (0);        // primary widget always has ID 0. 
    7372        widgetData = null;  // data is no longer needed: allow GC to collect (cannot safely delete) 
    7473         
    75         // Note: this should return an empty array, but nothing much should happen if it's not empty: 
    76         widget.adjust (mutableData);    // adjust/set size, etc. 
     74        // get border sizes: 
     75        border = rend.setSizable (isWSizable, isHSizable);  // depends on widget 
     76         
     77        // Note: this should return an empty array, but we shouldn't make a fuss if it's not empty: 
     78        widget.adjust (mutableData);    // adjust/set size, etc., depends on rend 
    7779        mutableData = null;             // no longer needed 
    7880         
     
    168170        return i; 
    169171    } 
    170  
     172     
    171173    IGui gui () { 
    172174        return gui_; 
    173175    } 
    174176     
    175     IRenderer renderer () { 
     177    void requestRedraw () { 
     178        gui_.requestRedraw; 
     179    } 
     180     
     181    IRenderer renderer () 
     182    in { 
     183        assert (rend !is null, "Window.renderer: rend is null"); 
     184    } body { 
    176185        return rend; 
    177186    } 
     
    250259    void clickEvent (ushort cx, ushort cy, ubyte b, bool state) { 
    251260        if (b == 1 && state == true) { 
    252             if (cx < x + resize.l || cx >= xw - resize.r || 
    253                 cy < y + resize.t || cy >= yh - resize.b) { // window is being resized 
    254                 /* check for resizes (different to above; use whole border giving larger area for 
    255                  * diagonal resizes). */ 
    256                 resizeType = RESIZE.NONE; 
     261            resizeType = rend.getResizeType (cx-x, cy-y, w,h); 
     262             
     263            if (resizeType != RESIZE_TYPE.NONE) {    // Some type of resize 
     264                // Set x/yDrag (unfortunately these need to be different for each edge) 
     265                if (resizeType & RESIZE_TYPE.L) 
     266                    xDrag = w + cx; 
     267                else if (resizeType & RESIZE_TYPE.R) 
     268                    xDrag = w - cx; 
    257269                 
    258                 if (isWSizable) { 
    259                     if (cx < x + border.l) { 
    260                         xDrag = w + cx; 
    261                         resizeType = RESIZE.L; 
    262                     } 
    263                     else if (cx >= xw - border.r) { 
    264                         xDrag = w - cx; 
    265                         resizeType = RESIZE.R; 
    266                     } 
    267                 } 
    268                 if (isHSizable) { 
    269                     if (cy < y + border.t) { 
    270                         yDrag = h + cy; 
    271                         resizeType |= RESIZE.T; 
    272                     } 
    273                     else if (cy >= yh - border.b) { 
    274                         yDrag = h - cy; 
    275                         resizeType |= RESIZE.B; 
    276                     } 
    277                 } 
     270                if (resizeType & RESIZE_TYPE.T) 
     271                    yDrag = h + cy; 
     272                else if (resizeType & RESIZE_TYPE.B) 
     273                    yDrag = h - cy; 
    278274                 
    279                 if (resizeType != RESIZE.NONE) {    // only if some valid size is being done 
    280                     gui_.addClickCallback (&endCallback); 
    281                     gui_.addMotionCallback (&resizeCallback); 
    282                 } 
    283             } else {                // window is being moved 
     275                // Add the callbacks (they use resizeType which has already been set) 
     276                gui_.addClickCallback (&endCallback); 
     277                gui_.addMotionCallback (&resizeCallback); 
     278            } else {                             // window is being moved 
    284279                xDrag = cx - x; 
    285280                yDrag = cy - y; 
     
    301296     
    302297private: 
    303     alias IRenderer.BorderDimensions    BorderDimensions; 
    304     alias IRenderer.BORDER_TYPES        BORDER_TYPES
     298    alias IRenderer.BorderDimensions BorderDimensions; 
     299    alias IRenderer.RESIZE_TYPE RESIZE_TYPE
    305300     
    306301    //BEGIN Window moving and resizing 
     
    309304    } 
    310305    void resizeCallback (ushort cx, ushort cy) { 
    311         if (resizeType & RESIZE.L) { 
     306        if (resizeType & RESIZE_TYPE.L) { 
    312307            int mw, nw; 
    313308            getMinimalSize (mw, nw);    // (only want mw) 
     
    318313            setPosition (mw, y); 
    319314        } 
    320         else if (resizeType & RESIZE.R) { 
     315        else if (resizeType & RESIZE_TYPE.R) { 
    321316            setSize (xDrag + cx, h); 
    322             setPosition (x, y); 
    323         } 
    324         if (resizeType & RESIZE.T) { 
     317            setPosition (x, y);         // required to call after setSize. 
     318        } 
     319        if (resizeType & RESIZE_TYPE.T) { 
    325320            int mh, nh; 
    326321            getMinimalSize (nh, mh); 
     
    331326            setPosition (x, mh); 
    332327        } 
    333         else if (resizeType & RESIZE.B) { 
     328        else if (resizeType & RESIZE_TYPE.B) { 
    334329            setSize (w, yDrag + cy); 
    335330            setPosition (x, y); 
    336331        } 
    337332    } 
    338     void endCallback (ushort cx, ushort cy, ubyte b, bool state) { 
     333    bool endCallback (ushort cx, ushort cy, ubyte b, bool state) { 
    339334        if (b == 1 && state == false) { 
    340335            // The mouse shouldn't have moved since the motion callback 
    341336            // was last called, so there's nothing else to do now. 
    342337            gui_.removeCallbacks (cast(void*) this); 
    343         } 
     338             
     339            return true;    // we've handled the up-click 
     340        } 
     341        return false;       // we haven't handled it 
    344342    } 
    345343    int xDrag, yDrag;               // where a drag starts relative to x and y 
    346     enum RESIZE : ubyte { 
    347         NONE = 0x0, L = 0x1, R = 0x2, T = 0x4, B = 0x8 
    348     } 
    349     RESIZE resizeType;              // Type of current resize 
     344    IRenderer.RESIZE_TYPE resizeType;   // Type of current resize 
    350345    //END Window moving and resizing 
    351346     
     
    353348    public char[] name;             // The window's name (id from config file) 
    354349    //bool edited = false;            // True if any widgets have been edited (excluding scaling) 
     350     
    355351    // Data used for saving and loading (null in between): 
    356352    int[][widgetID] widgetData = null;// Data for all widgets under this window 
     
    366362    int xw, yh;                     // x+w, y+h (frequent use by clickEvent) 
    367363    int widgetX, widgetY;           // Widget position (= window position plus BORDER_WIDTH) 
    368     int mw = -1, mh = -1;           // minimal size 
     364    int mw = -1, mh = -1;           // minimal size (negative means requires calculation) 
    369365     
    370366    BorderDimensions border;        // Total border size (move plus resize) 
    371     BorderDimensions resize;        // The outer resize part of the border 
    372367} 
  • mde/gui/widget/layout.d

    r40 r41  
    4646        // Get all sub-widgets 
    4747        subWidgets.length = rows*cols; 
    48         foreach (i, inout subWidget; subWidgets) { 
     48        foreach (i, ref subWidget; subWidgets) { 
    4949            subWidget = window.makeWidget (data[i+3]); 
    5050        } 
     
    7575            // Check row sizes are valid: 
    7676            //NOTE: this could be made optional 
    77             foreach (i, inout w; colW) 
     77            foreach (i, ref w; colW) 
    7878                if (w < colWMin[i]) w = colWMin[i]; 
    79             foreach (i, inout h; rowH) 
     79            foreach (i, ref h; rowH) 
    8080                if (h < rowHMin[i]) h = rowHMin[i]; 
    8181        } 
     
    200200         
    201201        // Calculate the overall minimal size, starting with the spacing: 
    202         mh = window.renderer.layoutSpacing;     // use temporarily 
     202        mh = window.renderer.layoutSpacing;     // use mh temporarily 
    203203        mw = mh * (cols - 1); 
    204204        mh *= (rows - 1); 
  • mde/sdl.d

    r36 r41  
    5454    openJoysticks ();                   // after SDL init 
    5555    cleanup.addFunc (&cleanupSDL, "cleanupSDL"); 
    56  
     56     
    5757    setupWindow(); 
    5858} 
     
    8484     
    8585    // Open a window 
     86    debug logger.trace ("Opening a window (this can crash if the libraries are messed up)"); 
    8687    if (SDL_SetVideoMode (w, h, 32, flags) is null) { 
    8788        logger.fatal ("Unable to set video mode:");