LCOV - code coverage report
Current view: top level - gdraw - gscrollbar.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 386 0.0 %
Date: 2017-08-04 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include "gdraw.h"
      28             : #include "gresource.h"
      29             : #include "ggadgetP.h"
      30             : #include "ustring.h"
      31             : 
      32             : static GBox scrollbar_box = GBOX_EMPTY; /* Don't initialize here */
      33             : static GBox thumb_box = GBOX_EMPTY; /* Don't initialize here */
      34             : int _GScrollBar_Width = 13;                     /* in points */
      35             : int _GScrollBar_StartTime=300, _GScrollBar_RepeatTime=200;
      36             : static int gscrollbar_inited = false;
      37             : 
      38             : static GGadget *GScrollBarCreateInitialized(struct gwindow *base, GGadgetData *gd,void *data);
      39             : static struct scrollbarinit sbinit = { 0, 40, 20, 10 };
      40             : static GGadgetCreateData scrollbar_gcd[] = {
      41             :     { GScrollBarCreateInitialized, { { 0, 0, 100, 13 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) &sbinit }, gg_visible, NULL, NULL }, NULL, NULL },
      42             :     { GScrollBarCreateInitialized, { { 0, 0, 100, 13 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) &sbinit }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL }
      43             : };
      44             : static GGadgetCreateData *sarray[] = { GCD_Glue, &scrollbar_gcd[0], GCD_Glue, &scrollbar_gcd[1], GCD_Glue, NULL, NULL };
      45             : static GGadgetCreateData scrollbarbox =
      46             :     { GHVGroupCreate, { { 2, 2, 0, 0 }, NULL, 0, 0, 0, 0, 0, NULL, { (GTextInfo *) sarray }, gg_visible|gg_enabled, NULL, NULL }, NULL, NULL };
      47             : static GResInfo gthumb_ri;
      48             : static GResInfo gscrollbar_ri = {
      49             :     &gthumb_ri, &ggadget_ri,&gthumb_ri, NULL,
      50             :     &scrollbar_box,
      51             :     NULL,
      52             :     &scrollbarbox,
      53             :     NULL,
      54             :     N_("ScrollBar"),
      55             :     N_("Scroll Bar"),
      56             :     "GScrollBar",
      57             :     "Gdraw",
      58             :     false,
      59             :     box_foreground_border_outer|omf_border_type|omf_border_width|
      60             :         omf_padding|omf_main_background,
      61             :     NULL,
      62             :     GBOX_EMPTY,
      63             :     NULL,
      64             :     NULL,
      65             :     NULL
      66             : };
      67             : static GResInfo gthumb_ri = {
      68             :     NULL, &ggadget_ri,&gscrollbar_ri, NULL,
      69             :     &thumb_box,
      70             :     NULL,
      71             :     &scrollbarbox,
      72             :     NULL,
      73             :     N_("SB Thumb"),
      74             :     N_("Scroll Bar Thumb"),
      75             :     "GScrollBarThumb",
      76             :     "Gdraw",
      77             :     true,
      78             :     omf_main_background|omf_border_width|omf_padding,
      79             :     NULL,
      80             :     GBOX_EMPTY,
      81             :     NULL,
      82             :     NULL,
      83             :     NULL
      84             : };
      85             : 
      86           0 : static void GScrollBarChanged(GScrollBar *gsb, enum sb sbtype, int32 pos) {
      87             :     GEvent e;
      88             :     int active_len;
      89             : 
      90           0 :     if ( gsb->g.vert ) {
      91           0 :         active_len = gsb->g.inner.height;
      92             :     } else {
      93           0 :         active_len = gsb->g.inner.width;
      94             :     }
      95           0 :     if ( active_len<=0 )
      96           0 :         active_len = 1;
      97             : 
      98           0 :     e.type = et_controlevent;
      99           0 :     e.w = gsb->g.base;
     100           0 :     e.u.control.subtype = et_scrollbarchange;
     101           0 :     e.u.control.g = &gsb->g;
     102           0 :     e.u.control.u.sb.type = sbtype;
     103           0 :     e.u.control.u.sb.pos = (pos-gsb->thumboff)*(gsb->sb_max-gsb->sb_min)/active_len +
     104           0 :             gsb->sb_min;
     105           0 :     if ( e.u.control.u.sb.pos > gsb->sb_max-gsb->sb_mustshow )
     106           0 :         e.u.control.u.sb.pos = gsb->sb_max-gsb->sb_mustshow;
     107           0 :     if ( e.u.control.u.sb.pos < gsb->sb_min )
     108           0 :         e.u.control.u.sb.pos = gsb->sb_min;
     109             : 
     110           0 :     if ( gsb->g.handle_controlevent!=NULL )
     111           0 :         (gsb->g.handle_controlevent)(&gsb->g,&e);
     112             :     else
     113           0 :         GDrawPostEvent(&e);
     114           0 : }
     115             : 
     116           0 : static void draw_thumb(GWindow pixmap, GScrollBar *gsb) {
     117             :     GRect thumbrect, thumbinner, old;
     118             :     int lw, skip, i;
     119             : 
     120           0 :     GDrawPushClip(pixmap,&gsb->g.inner,&old);
     121           0 :     thumbrect = gsb->g.inner;
     122           0 :     if ( gsb->g.vert ) {
     123           0 :         thumbrect.y = gsb->g.inner.y+gsb->thumbpos;
     124           0 :         thumbrect.height = gsb->thumbsize;
     125             :     } else {
     126           0 :         thumbrect.x = gsb->g.inner.x+gsb->thumbpos;
     127           0 :         thumbrect.width = gsb->thumbsize;
     128             :     }
     129           0 :     thumbinner.x = thumbrect.x+gsb->thumbborder;
     130           0 :     thumbinner.y = thumbrect.y+gsb->thumbborder;
     131           0 :     thumbinner.width = thumbrect.width-2*gsb->thumbborder;
     132           0 :     thumbinner.height = thumbrect.height-2*gsb->thumbborder;
     133             : 
     134           0 :     GBoxDrawBackground(pixmap,&thumbrect,gsb->thumbbox, gsb->g.state,false);
     135           0 :     GBoxDrawBorder(pixmap,&thumbrect,gsb->thumbbox,gsb->g.state,false);
     136             : 
     137           0 :     lw = GDrawPointsToPixels(gsb->g.base,1);
     138           0 :     skip = GDrawPointsToPixels(gsb->g.base,3);
     139           0 :     GDrawSetLineWidth(pixmap,lw);
     140           0 :     if ( gsb->g.vert ) {
     141           0 :         for ( i = thumbinner.y + skip; i<thumbinner.y+thumbinner.height-skip;
     142           0 :                 i += skip+2*lw ) {
     143           0 :             GDrawDrawLine(pixmap,thumbinner.x+lw, i, thumbinner.x+thumbinner.width-2*lw, i,
     144           0 :                     gsb->thumbbox->border_brightest );
     145           0 :             GDrawDrawLine(pixmap,thumbinner.x+lw, i+lw, thumbinner.x+thumbinner.width-2*lw, i+lw,
     146           0 :                     gsb->thumbbox->border_darkest );
     147             :         }
     148             :     } else {
     149           0 :         for ( i = thumbinner.x + skip; i<thumbinner.x+thumbinner.width-skip;
     150           0 :                 i += skip+2*lw ) {
     151           0 :             GDrawDrawLine(pixmap,i, thumbinner.y+lw, i, thumbinner.y+thumbinner.height-2*lw,
     152           0 :                     gsb->thumbbox->border_brightest );
     153           0 :             GDrawDrawLine(pixmap,i+lw, thumbinner.y+lw, i+lw, thumbinner.y+thumbinner.height-2*lw, 
     154           0 :                     gsb->thumbbox->border_darkest );
     155             :         }
     156             :     }
     157           0 :     GDrawPopClip(pixmap,&old);
     158           0 : }
     159             : 
     160           0 : static void draw_arrow(GWindow pixmap, GScrollBar *gsb, int which) {
     161             :     GPoint pts[5];
     162           0 :     int point = GDrawPointsToPixels(gsb->g.base,1);
     163           0 :     int cnt = 4;
     164           0 :     Color fill = gsb->thumbbox->main_foreground;
     165             : 
     166           0 :     if ( fill == COLOR_DEFAULT )
     167           0 :         fill = GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap));
     168             : 
     169           0 :     switch ( which ) {
     170             :       case 0:           /* Horizontal left arrow */
     171           0 :         pts[0].y = (gsb->g.r.y+(gsb->g.r.height-1)/2);
     172           0 :                 pts[0].x = gsb->g.r.x + 2*point;
     173           0 :         pts[1].y = gsb->g.r.y + point;
     174           0 :                 pts[1].x = pts[0].x + (gsb->g.r.height-1)/2-point ;
     175           0 :         pts[2].y = gsb->g.r.y+gsb->g.r.height-1 - point;
     176           0 :                 pts[2].x = pts[1].x;
     177           0 :         pts[3] = pts[0];
     178           0 :         if ( !(gsb->g.inner.height&1 )) {
     179           0 :             ++pts[3].y;
     180           0 :             pts[4] = pts[0];
     181           0 :             cnt = 5;
     182             :         }
     183           0 :         GDrawFillPoly(pixmap,pts,cnt,fill);
     184           0 :         GDrawDrawLine(pixmap,pts[0].x,pts[0].y,pts[1].x,pts[1].y,
     185           0 :                 gsb->thumbbox->border_brightest);
     186           0 :         GDrawDrawLine(pixmap,pts[2].x,pts[2].y,pts[3].x,pts[3].y,
     187           0 :                 gsb->thumbbox->border_darker);
     188           0 :         GDrawDrawLine(pixmap,pts[1].x,pts[1].y,pts[2].x,pts[2].y,
     189           0 :                 gsb->thumbbox->border_darkest);
     190           0 :       break;
     191             :       case 1:           /* Vertical up arrow */
     192           0 :         pts[0].x = (gsb->g.r.x+(gsb->g.r.width-1)/2);
     193           0 :                 pts[0].y = gsb->g.r.y + 2*point;
     194           0 :         pts[1].x = gsb->g.r.x + point;
     195           0 :                 pts[1].y = pts[0].y + (gsb->g.r.width-1)/2-point ;
     196           0 :         pts[2].x = gsb->g.r.x+gsb->g.r.width-1 - point;
     197           0 :                 pts[2].y = pts[1].y;
     198           0 :         pts[3] = pts[0];
     199           0 :         if ( !(gsb->g.inner.width&1 )) {
     200           0 :             ++pts[3].x;
     201           0 :             pts[4] = pts[0];
     202           0 :             cnt = 5;
     203             :         }
     204           0 :         GDrawFillPoly(pixmap,pts,cnt,fill);
     205           0 :         GDrawDrawLine(pixmap,pts[0].x,pts[0].y,pts[1].x,pts[1].y,
     206           0 :                 gsb->thumbbox->border_brightest);
     207           0 :         GDrawDrawLine(pixmap,pts[2].x,pts[2].y,pts[3].x,pts[3].y,
     208           0 :                 gsb->thumbbox->border_darker);
     209           0 :         GDrawDrawLine(pixmap,pts[1].x,pts[1].y,pts[2].x,pts[2].y,
     210           0 :                 gsb->thumbbox->border_darkest);
     211           0 :       break;
     212             :       case 2:           /* Horizontal right arrow */
     213           0 :         pts[0].y = (gsb->g.r.y+(gsb->g.r.height-1)/2);
     214           0 :                 pts[0].x = gsb->g.r.x + gsb->g.r.width-1 - 2*point;
     215           0 :         pts[1].y = gsb->g.r.y + point;
     216           0 :                 pts[1].x = pts[0].x - ((gsb->g.r.height-1)/2-point);
     217           0 :         pts[2].y = gsb->g.r.y+gsb->g.r.height-1 - point;
     218           0 :                 pts[2].x = pts[1].x;
     219           0 :         pts[3] = pts[0];
     220           0 :         if ( !(gsb->g.inner.height&1 )) {
     221           0 :             ++pts[3].y;
     222           0 :             pts[4] = pts[0];
     223           0 :             cnt = 5;
     224             :         }
     225           0 :         GDrawFillPoly(pixmap,pts,cnt,fill);
     226           0 :         GDrawDrawLine(pixmap,pts[0].x,pts[0].y,pts[1].x,pts[1].y,
     227           0 :                 gsb->thumbbox->border_darkest);
     228           0 :         GDrawDrawLine(pixmap,pts[2].x,pts[2].y,pts[3].x,pts[3].y,
     229           0 :                 gsb->thumbbox->border_darker);
     230           0 :         GDrawDrawLine(pixmap,pts[1].x,pts[1].y,pts[2].x,pts[2].y,
     231           0 :                 gsb->thumbbox->border_brightest);
     232           0 :       break;
     233             :       case 3:           /* Vertical down arrow */
     234           0 :         pts[0].x = (gsb->g.r.x+(gsb->g.r.width-1)/2);
     235           0 :                 pts[0].y = gsb->g.r.y + gsb->g.r.height-1 - 2*point;
     236           0 :         pts[1].x = gsb->g.r.x + point;
     237           0 :                 pts[1].y = pts[0].y - ((gsb->g.r.width-1)/2-point);
     238           0 :         pts[2].x = gsb->g.r.x+gsb->g.r.width-1 - point;
     239           0 :                 pts[2].y = pts[1].y;
     240           0 :         pts[3] = pts[0];
     241           0 :         if ( !(gsb->g.inner.width&1 )) {
     242           0 :             ++pts[3].x;
     243           0 :             pts[4] = pts[0];
     244           0 :             cnt = 5;
     245             :         }
     246           0 :         GDrawFillPoly(pixmap,pts,cnt,fill);
     247           0 :         GDrawDrawLine(pixmap,pts[0].x,pts[0].y,pts[1].x,pts[1].y,
     248           0 :                 gsb->thumbbox->border_darkest);
     249           0 :         GDrawDrawLine(pixmap,pts[2].x,pts[2].y,pts[3].x,pts[3].y,
     250           0 :                 gsb->thumbbox->border_darker);
     251           0 :         GDrawDrawLine(pixmap,pts[1].x,pts[1].y,pts[2].x,pts[2].y,
     252           0 :                 gsb->thumbbox->border_brightest);
     253           0 :       break;
     254             :     }
     255           0 : }
     256             : 
     257             : static void GScrollBarFit(GScrollBar *gsb);
     258             : 
     259           0 : static int gscrollbar_expose(GWindow pixmap, GGadget *g, GEvent *event) {
     260           0 :     GScrollBar *gsb = (GScrollBar *) g;
     261           0 :     GBox box = *(g->box);
     262             :     GRect old1;
     263             :     GRect r;
     264             :     int ar;
     265             : 
     266           0 :     if ( g->state == gs_invisible )
     267           0 : return( false );
     268             : 
     269             :     /* In case border was changed in resource editor, */
     270             :     /* the scrollbar thumb inside must be refitted. */
     271           0 :     GScrollBarFit(gsb);
     272             : 
     273           0 :     GDrawPushClip(pixmap,&g->r,&old1);
     274             : 
     275           0 :     r = g->r;
     276           0 :     ar = gsb->arrowsize - gsb->sbborder;
     277           0 :     if ( gsb->g.vert ) { r.y += ar ; r.height -= 2*ar; }
     278           0 :     else { r.x += ar; r.width -= 2*ar; }
     279             : 
     280             :     /* Mimick old border behavior to retain compatibility with older themes, */
     281             :     /* but match border shape with that of background. */
     282           0 :     box.flags = box_foreground_border_outer;
     283           0 :     box.border_width = 0;
     284           0 :     GBoxDrawBackground(pixmap,&g->r,g->box,g->state,false);
     285           0 :     GBoxDrawBackground(pixmap,&r,g->box,gs_pressedactive,false);
     286           0 :     GBoxDrawBorder(pixmap,&g->r,&box,g->state,false);
     287           0 :     GBoxDrawBorder(pixmap,&r,g->box,g->state,false);
     288             : 
     289           0 :     draw_thumb(pixmap,gsb); /* sets line width for arrows too */
     290           0 :     draw_arrow(pixmap,gsb,gsb->g.vert);
     291           0 :     draw_arrow(pixmap,gsb,gsb->g.vert|2);
     292             : 
     293           0 :     GDrawPopClip(pixmap,&old1);
     294           0 : return( true );
     295             : }
     296             : 
     297           0 : static int gscrollbar_mouse(GGadget *g, GEvent *event) {
     298           0 :     GScrollBar *gsb = (GScrollBar *) g;
     299             :     int active_pos, active_len;
     300             : 
     301           0 :     if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused ))
     302           0 : return( false );
     303           0 :     if ( event->type == et_crossing )
     304           0 : return( false );
     305             : 
     306           0 :     if ( gsb->g.vert ) {
     307           0 :         active_pos = event->u.mouse.y-g->inner.y;
     308           0 :         active_len = g->inner.height;
     309             :     } else {
     310           0 :         active_pos = event->u.mouse.x-g->inner.x;
     311           0 :         active_len = g->inner.width;
     312             :     }
     313             : 
     314           0 :     if ( (event->type==et_mouseup || event->type==et_mousedown) &&
     315           0 :             (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
     316             :         /* X treats scroll wheels as though they send events from buttons 4 and 5 */
     317             :         /* Badly configured wacom mice send "p5 r5 p4 r4" or "p4 r4 p5 r5" */
     318             :         /*  properly configured mice just send "p4 r4" or "p5 r5" */
     319             :         /* And apple's mouse with a scrollwheel sends buttons 6&7 for horizontal*/
     320             :         /*  scrolling */
     321             :         /* Convention is that shift-vertical scroll=horizontal scroll */
     322             :         /*                    control-vertical scroll=minimize/maximize */
     323           0 :         if ( event->type==et_mousedown ) {
     324           0 :             GDrawCancelTimer(gsb->pressed); gsb->pressed = NULL;
     325           0 :             int isv = event->u.mouse.button<=5;
     326           0 :             if ( event->u.mouse.state&ksm_shift ) isv = !isv;
     327           0 :             if ( !isv && g->vert )
     328           0 : return( false );        /* Allow horizontal scrolling with normal scroll but not vice versa */
     329           0 :             else if ( event->u.mouse.state&ksm_control )
     330           0 : return( false );
     331           0 :             if ( event->u.mouse.button==5 || event->u.mouse.button==7 ) {
     332           0 :                 GScrollBarChanged(gsb,et_sb_down,0);
     333           0 :             } else if ( event->u.mouse.button==4 || event->u.mouse.button==6 ) {
     334           0 :                 GScrollBarChanged(gsb,et_sb_up,0);
     335             :             }
     336             :         }
     337           0 : return( true );
     338             :     }
     339             : 
     340           0 :     if ( event->type == et_mousedown && GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
     341           0 :         GDrawCancelTimer(gsb->pressed); gsb->pressed = NULL;
     342           0 :         if ( event->u.mouse.button!=1 ) {
     343           0 :             gsb->thumbpressed = true;
     344           0 :             gsb->thumboff = 0;
     345           0 :             active_pos = event->u.mouse.y-g->inner.y;
     346           0 :             GScrollBarChanged(gsb,et_sb_thumb,active_pos);
     347           0 :         } else if ( active_pos >= gsb->thumbpos &&
     348           0 :                 active_pos < gsb->thumbpos+gsb->thumbsize ) {
     349           0 :             gsb->thumbpressed = true;
     350           0 :             gsb->thumboff = active_pos-gsb->thumbpos;
     351           0 :         } else if ( active_pos < gsb->thumbpos &&
     352           0 :                 (event->u.mouse.state&(ksm_control|ksm_meta)) ) {
     353           0 :             gsb->thumbpressed = true;
     354           0 :             gsb->thumboff = active_pos;
     355           0 :             GScrollBarChanged(gsb,et_sb_top,0);
     356           0 :         } else if ( active_pos >= gsb->thumbpos+gsb->thumbsize &&
     357           0 :                 (event->u.mouse.state&(ksm_control|ksm_meta)) ) {
     358           0 :             gsb->thumbpressed = true;
     359           0 :             gsb->thumboff = active_pos-active_len+gsb->thumbsize;
     360           0 :             GScrollBarChanged(gsb,et_sb_bottom,0);
     361             :         } else {
     362           0 :             if ( active_pos<0 )
     363           0 :                 gsb->repeatcmd = et_sb_up;
     364           0 :             else if ( active_pos >= active_len )
     365           0 :                 gsb->repeatcmd = et_sb_down;
     366           0 :             else if ( active_pos < gsb->thumbpos )
     367           0 :                 gsb->repeatcmd = et_sb_uppage;
     368             :             else /* if ( active_pos > gsb->thumbpos+gsb->thumbsize )*/
     369           0 :                 gsb->repeatcmd = et_sb_downpage;
     370           0 :             GScrollBarChanged(gsb,gsb->repeatcmd,0);
     371           0 :             gsb->pressed = GDrawRequestTimer(g->base,_GScrollBar_StartTime,_GScrollBar_RepeatTime,NULL);
     372             :         }
     373           0 :     } else if ( event->type == et_mousemove && gsb->thumbpressed ) {
     374           0 :         GDrawSkipMouseMoveEvents(gsb->g.base,event);
     375           0 :         if ( gsb->g.vert ) {
     376           0 :             active_pos = event->u.mouse.y-g->inner.y;
     377             :         } else {
     378           0 :             active_pos = event->u.mouse.x-g->inner.x;
     379             :         }
     380           0 :         GScrollBarChanged(gsb,et_sb_thumb,active_pos);
     381           0 :     } else if ( event->type == et_mouseup && (gsb->thumbpressed || gsb->pressed)) {
     382           0 :         if ( gsb->thumbpressed )
     383           0 :             GScrollBarChanged(gsb,et_sb_thumbrelease,active_pos);
     384           0 :         GDrawCancelTimer(gsb->pressed); gsb->pressed = NULL;
     385           0 :         gsb->thumbpressed = false;
     386           0 :     } else if ( event->type == et_mousemove && !gsb->pressed &&
     387           0 :             g->popup_msg!=NULL && GGadgetWithin(g,event->u.mouse.x,event->u.mouse.y)) {
     388           0 :         GGadgetPreparePopup(g->base,g->popup_msg);
     389           0 : return( true );
     390             :     } else
     391           0 : return( false );
     392             : 
     393           0 : return( true );
     394             : }
     395             : 
     396           0 : static int gscrollbar_timer(GGadget *g, GEvent *event) {
     397           0 :     GScrollBar *gsb = (GScrollBar *) g;
     398             : 
     399           0 :     if ( event->u.timer.timer == gsb->pressed ) {
     400           0 :         GScrollBarChanged(gsb,gsb->repeatcmd,0);
     401           0 : return( true );
     402             :     }
     403           0 : return( false );
     404             : }
     405             : 
     406           0 : static void gscrollbar_destroy(GGadget *g) {
     407           0 :     GScrollBar *gsb = (GScrollBar *) g;
     408             : 
     409           0 :     if ( gsb==NULL )
     410           0 : return;
     411           0 :     GDrawCancelTimer(gsb->pressed);
     412           0 :     _ggadget_destroy(g);
     413             : }
     414             : 
     415           0 : static void gscrollbar_get_desired_size(GGadget *g, GRect *outer, GRect *inner) {
     416           0 :     int bp = GBoxBorderWidth(g->base,g->box);
     417           0 :     GScrollBar *gsb = (GScrollBar *) g;
     418             :     int width, height;
     419             :     int minheight, sbw;
     420             : 
     421           0 :     sbw = GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width);
     422           0 :     minheight = 2*(gsb->thumbborder+gsb->arrowsize) + GDrawPointsToPixels(gsb->g.base,2);
     423           0 :     if ( g->vert ) {
     424           0 :         width = sbw;
     425           0 :         height = minheight;
     426             :     } else {
     427           0 :         width = minheight;
     428           0 :         height = sbw;
     429             :     }
     430             : 
     431           0 :     if ( inner!=NULL ) {
     432           0 :         inner->x = inner->y = 0;
     433           0 :         inner->width = width; inner->height = height;
     434             :     }
     435           0 :     if ( outer!=NULL ) {
     436           0 :         outer->x = outer->y = 0;
     437           0 :         outer->width = width+2*bp; outer->height = height+2*bp;
     438             :     }
     439           0 : }
     440             : 
     441             : struct gfuncs gscrollbar_funcs = {
     442             :     0,
     443             :     sizeof(struct gfuncs),
     444             : 
     445             :     gscrollbar_expose,
     446             :     gscrollbar_mouse,
     447             :     NULL,
     448             :     NULL,
     449             :     NULL,
     450             :     gscrollbar_timer,
     451             :     NULL,
     452             : 
     453             :     _ggadget_redraw,
     454             :     _ggadget_move,
     455             :     _ggadget_resize,
     456             :     _ggadget_setvisible,
     457             :     _ggadget_setenabled,
     458             :     _ggadget_getsize,
     459             :     _ggadget_getinnersize,
     460             : 
     461             :     gscrollbar_destroy,
     462             : 
     463             :     NULL,
     464             :     NULL,
     465             :     NULL,
     466             :     NULL,
     467             :     NULL,
     468             : 
     469             :     NULL,
     470             :     NULL,
     471             : 
     472             :     NULL,
     473             :     NULL,
     474             :     NULL,
     475             :     NULL,
     476             :     NULL,
     477             :     NULL,
     478             :     NULL,
     479             :     NULL,
     480             :     NULL,
     481             :     NULL,
     482             :     NULL,
     483             : 
     484             :     gscrollbar_get_desired_size,
     485             :     NULL,
     486             :     NULL,
     487             :     NULL
     488             : };
     489             : 
     490           0 : static void GScrollBarInit() {
     491           0 :     _GGadgetCopyDefaultBox(&scrollbar_box);
     492           0 :     _GGadgetCopyDefaultBox(&thumb_box);
     493           0 :     scrollbar_box.border_type = bt_lowered;
     494           0 :     scrollbar_box.border_width = 1;
     495           0 :     scrollbar_box.padding = 0;
     496           0 :     scrollbar_box.flags |= box_foreground_border_outer;
     497           0 :     scrollbar_box.main_background = GDrawColorBrighten(scrollbar_box.main_background, 0x10);
     498           0 :     thumb_box.main_background = GDrawColorDarken(thumb_box.main_background,0x8);
     499           0 :     thumb_box.border_width = 1;
     500           0 :     thumb_box.padding = 0;
     501           0 :     _GGadgetInitDefaultBox("GScrollBar.",&scrollbar_box,NULL);
     502           0 :     _GGadgetInitDefaultBox("GScrollBarThumb.",&thumb_box,NULL);
     503           0 :     _GScrollBar_Width = GResourceFindInt("GScrollBar.Width",_GScrollBar_Width);
     504           0 :     _GScrollBar_StartTime = GResourceFindInt("GScrollBar.StartupTime",_GScrollBar_StartTime);
     505           0 :     _GScrollBar_RepeatTime = GResourceFindInt("GScrollBar.RepeatTime",_GScrollBar_RepeatTime);
     506           0 :     gscrollbar_inited = true;
     507           0 : }
     508             : 
     509           0 : static void GScrollBarFit(GScrollBar *gsb) {
     510             :     int minheight;
     511             : 
     512           0 :     gsb->sbborder = GBoxBorderWidth(gsb->g.base,gsb->g.box);
     513           0 :     gsb->thumbborder = GBoxBorderWidth(gsb->g.base,gsb->thumbbox);
     514             :     /* FIXME: workaround for incorrect calculation. */
     515           0 :     if ( gsb->thumbborder > 5 ) gsb->thumbborder = 5;
     516           0 :     gsb->arrowsize = gsb->sbborder +
     517           0 :             2*GDrawPointsToPixels(gsb->g.base,2) +
     518           0 :             GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width)/2-
     519           0 :             2*GDrawPointsToPixels(gsb->g.base,1);
     520           0 :     minheight = 2*(gsb->thumbborder+gsb->arrowsize) + GDrawPointsToPixels(gsb->g.base,2);
     521             : 
     522           0 :     if ( gsb->g.vert ) {
     523           0 :         if ( gsb->g.r.width==0 )
     524           0 :             gsb->g.r.width = GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width);
     525           0 :         if ( gsb->g.r.height< minheight )
     526           0 :             gsb->g.r.height = minheight;
     527           0 :         gsb->g.inner.x = gsb->g.r.x+gsb->sbborder;
     528           0 :         gsb->g.inner.width = gsb->g.r.width - 2*gsb->sbborder;
     529           0 :         gsb->g.inner.y = gsb->g.r.y+gsb->arrowsize;
     530           0 :         gsb->g.inner.height = gsb->g.r.height - 2*gsb->arrowsize;
     531             :     } else {
     532           0 :         if ( gsb->g.r.height==0 )
     533           0 :             gsb->g.r.height = GDrawPointsToPixels(gsb->g.base,_GScrollBar_Width);
     534           0 :         if ( gsb->g.r.width< minheight )
     535           0 :             gsb->g.r.width = minheight;
     536           0 :         gsb->g.inner.x = gsb->g.r.x+gsb->arrowsize;
     537           0 :         gsb->g.inner.width = gsb->g.r.width - 2*gsb->arrowsize;
     538           0 :         gsb->g.inner.y = gsb->g.r.y+gsb->sbborder;
     539           0 :         gsb->g.inner.height = gsb->g.r.height - 2*gsb->sbborder;
     540             :     }
     541           0 : }
     542             : 
     543           0 : static GScrollBar *_GScrollBarCreate(GScrollBar *gsb, struct gwindow *base, GGadgetData *gd,void *data, GBox *def) {
     544             : 
     545           0 :     if ( !gscrollbar_inited )
     546           0 :         GScrollBarInit();
     547           0 :     gsb->g.funcs = &gscrollbar_funcs;
     548           0 :     gd->flags |= gg_pos_use0;
     549           0 :     _GGadget_Create(&gsb->g,base,gd,data,def);
     550             : 
     551           0 :     gsb->g.takes_input = true;
     552           0 :     if ( gd->flags & gg_sb_vert )
     553           0 :         gsb->g.vert = true;
     554           0 :     gsb->thumbbox = &thumb_box;
     555             : 
     556           0 :     GScrollBarFit(gsb);
     557           0 :     if ( gd->u.sbinit!=NULL )
     558           0 :         GScrollBarSetMustShow(&gsb->g,
     559           0 :                 gd->u.sbinit->sb_min,
     560           0 :                 gd->u.sbinit->sb_max,
     561           0 :                 gd->u.sbinit->sb_pagesize,
     562           0 :                 gd->u.sbinit->sb_pos);
     563             : 
     564           0 :     if ( gd->flags & gg_group_end )
     565           0 :         _GGadgetCloseGroup(&gsb->g);
     566           0 : return( gsb );
     567             : }
     568             : 
     569           0 : static GGadget *GScrollBarCreateInitialized(struct gwindow *base, GGadgetData *gd,void *data) {
     570           0 :     GScrollBar *gsb = _GScrollBarCreate(calloc(1,sizeof(GScrollBar)),base,gd,data,&scrollbar_box);
     571             : 
     572           0 : return( &gsb->g );
     573             : }
     574             : 
     575           0 : GGadget *GScrollBarCreate(struct gwindow *base, GGadgetData *gd,void *data) {
     576             :     GScrollBar *gsb;
     577           0 :     struct scrollbarinit *hold = gd->u.sbinit;
     578             : 
     579           0 :     gd->u.sbinit = NULL;
     580           0 :     gsb = _GScrollBarCreate(calloc(1,sizeof(GScrollBar)),base,gd,data,&scrollbar_box);
     581           0 :     gd->u.sbinit = hold;
     582             : 
     583           0 : return( &gsb->g );
     584             : }
     585             : 
     586           0 : int32 GScrollBarGetPos(GGadget *g) {
     587           0 : return( ((GScrollBar *) g)->sb_pos );
     588             : }
     589             : 
     590           0 : int32 GScrollBarAddToPos(GGadget *g,int32 pos) {
     591           0 :     return GScrollBarSetPos( g, GScrollBarGetPos(g) + pos );
     592             : }
     593             : 
     594             : 
     595           0 : int32 GScrollBarSetPos(GGadget *g,int32 pos) {
     596           0 :     GScrollBar *gsb = (GScrollBar *) g;
     597             : 
     598           0 :     if ( pos>gsb->sb_max-gsb->sb_mustshow )
     599           0 :         pos = gsb->sb_max-gsb->sb_mustshow;
     600           0 :     if ( pos<gsb->sb_min )
     601           0 :         pos = gsb->sb_min;
     602           0 :     gsb->sb_pos = pos;
     603             : 
     604           0 :     if ( pos==gsb->sb_min || gsb->sb_min==gsb->sb_max )
     605           0 :         gsb->thumbpos = 0;
     606             :     else
     607           0 :         gsb->thumbpos =
     608           0 :             ((gsb->g.vert?gsb->g.inner.height:gsb->g.inner.width)-gsb->size_offset)
     609           0 :               *(pos-gsb->sb_min)/(gsb->sb_max-gsb->sb_min);
     610           0 :     _ggadget_redraw(g);
     611           0 : return( pos );
     612             : }
     613             : 
     614           0 : void GScrollBarSetMustShow(GGadget *g, int32 sb_min, int32 sb_max, int32 sb_pagesize,
     615             :         int32 sb_mustshow ) {
     616           0 :     GScrollBar *gsb = (GScrollBar *) g;
     617             : 
     618           0 :     if ( sb_min>sb_max || sb_pagesize<=0 ) {
     619           0 :         GDrawIError("Invalid scrollbar bounds min=%d max=%d, pagesize=%d",
     620             :                 sb_min, sb_max, sb_pagesize );
     621           0 : return;
     622             :     }
     623           0 :     gsb->sb_min = sb_min;
     624           0 :     gsb->sb_max = sb_max;
     625           0 :     gsb->sb_pagesize = sb_pagesize;
     626           0 :     gsb->sb_mustshow = sb_mustshow;
     627           0 :     gsb->size_offset = 0;
     628           0 :     gsb->thumbsize = (gsb->g.vert?gsb->g.inner.height:gsb->g.inner.width);
     629           0 :     if ( sb_max-sb_min > sb_pagesize )
     630           0 :         gsb->thumbsize = (gsb->thumbsize*gsb->sb_pagesize)/(sb_max-sb_min);
     631           0 :     if ( gsb->thumbsize<2*gsb->thumbborder+10 ) {
     632           0 :         gsb->size_offset = 2*gsb->thumbborder+10 - gsb->thumbsize;
     633           0 :         gsb->thumbsize = 2*gsb->thumbborder+10;
     634           0 :         if ( gsb->thumbsize>(gsb->g.vert?gsb->g.inner.height:gsb->g.inner.width) ) {
     635           0 :             gsb->size_offset = 0;
     636           0 :             gsb->thumbsize = (gsb->g.vert?gsb->g.inner.height:gsb->g.inner.width);
     637             :         }
     638             :     }
     639           0 :     GScrollBarSetPos(g,gsb->sb_pos);
     640             : }
     641             : 
     642           0 : void GScrollBarSetBounds(GGadget *g, int32 sb_min, int32 sb_max, int32 sb_pagesize ) {
     643           0 :     GScrollBarSetMustShow(g,sb_min,sb_max,sb_pagesize,sb_pagesize);
     644           0 : }
     645             : 
     646           0 : void GScrollBarGetBounds(GGadget *g, int32 *sb_min, int32 *sb_max, int32 *sb_pagesize ) {
     647           0 :     GScrollBar *gsb = (GScrollBar *) g;
     648           0 :     *sb_min = gsb->sb_min;
     649           0 :     *sb_max = gsb->sb_max;
     650           0 :     *sb_pagesize = gsb->sb_pagesize;
     651           0 : }
     652             : 
     653           0 : GResInfo *_GScrollBarRIHead(void) {
     654           0 :     if ( !gscrollbar_inited )
     655           0 :         GScrollBarInit();
     656           0 : return( &gscrollbar_ri );
     657             : }

Generated by: LCOV version 1.10