scroller.c

来自「SEAL是DOS 下的32位保护模式的GUI程序」· C语言 代码 · 共 1,223 行 · 第 1/2 页

C
1,223
字号
    o->scroller->scroll_size(o->scroller, &maxx, NULL);

    size = (l_rect)((double)sizex*((double)sizex_scroller/(double)(max(1, maxx))));

    if ( size < MINIMUM_SCROLLBOX_SIZE ) dx = MINIMUM_SCROLLBOX_SIZE-size;

    pos = (l_rect)((double)(sizex-dx)*((double)o->scroller->scrollx/(double)(max(1, maxx))));

    if ( pos+size > sizex ) pos = lmax(0, sizex-size);

    return pos;

  };

  return 0;

};



/* scroller functions */

l_bool   scroller_done ( p_object o )
{
  if ( SCROLLER(o)->horbar )
   view_done(OBJECT(SCROLLER(o)->horbar));
  if ( SCROLLER(o)->verbar )
   view_done(OBJECT(SCROLLER(o)->verbar));
  return view_done(o);

};


void   scroller_setup ( p_object o )
{
  p_object owner = NULL;

  view_setup(o);

  owner = o->owner_view(o);

  if ( owner ) { /* if owner_view exist */

    if ( SCROLLER(o)->flags & SF_HORSCROLLBAR &&
        !SCROLLER(o)->horbar ) { /* horizontal scrollbar */

         t_rect r = VIEW(o)->bounds;

         r = rect_assign(r.a.x, r.b.y+1, r.b.x, r.b.y+1+STANDARD_SCROLLBAR_WIDTH);

         SCROLLER(o)->horbar = hscrollbar_init(_malloc(sizeof(t_hscrollbar)), r, SCROLLER(o));

         if ( SCROLLER(o)->horbar )  /* set to top_select if listbox was set too */

               OBJECT(SCROLLER(o)->horbar)->set_options(OBJECT(SCROLLER(o)->horbar), OB_OF_TOPSELECT, o->is_options(o, OB_OF_TOPSELECT));

         owner->insert(owner, OBJECT(SCROLLER(o)->horbar));

    };

    if ( SCROLLER(o)->flags & SF_VERSCROLLBAR &&
        !SCROLLER(o)->verbar ) { /* vertical scrollbar */

         t_rect r = VIEW(o)->bounds;

         r = rect_assign(r.b.x+1, r.a.y, r.b.x+1+STANDARD_SCROLLBAR_WIDTH, r.b.y);

         SCROLLER(o)->verbar = vscrollbar_init(_malloc(sizeof(t_vscrollbar)), r, SCROLLER(o));

         if ( SCROLLER(o)->verbar ) /* set to top_select if listbox was set too */

            OBJECT(SCROLLER(o)->verbar)->set_options(OBJECT(SCROLLER(o)->verbar), OB_OF_TOPSELECT, o->is_options(o, OB_OF_TOPSELECT));

         owner->insert(owner, OBJECT(SCROLLER(o)->verbar));

    };

  };

};


void   scroller_change_bounds ( p_view o, t_rect nr )
{

  view_change_bounds(o, nr);

  if ( SCROLLER(o)->horbar ) {

    p_view hb = VIEW(SCROLLER(o)->horbar);
    t_rect r  = o->bounds;

    hb->change_bounds(hb, rect_assign(r.a.x, r.b.y+1, r.b.x, r.b.y+1+STANDARD_SCROLLBAR_WIDTH));

  };

  if ( SCROLLER(o)->verbar ) {

    p_view vb = VIEW(SCROLLER(o)->verbar);
    t_rect r  = o->bounds;

    vb->change_bounds(vb, rect_assign(r.b.x+1, r.a.y, r.b.x+1+STANDARD_SCROLLBAR_WIDTH, r.b.y));

  };

};


void   scroller_background ( p_view o, BITMAP *out, t_rect r )
{
  if ( o->brush.background ) {

    t_rect i = {0, 0, IMAGE_WIDTH(o->brush.background),
                      IMAGE_HEIGHT(o->brush.background)};

    r.a.x -= SCROLLER(o)->scrollx;
    r.a.y -= SCROLLER(o)->scrolly;

    if ( o->brush.state & BRUSH_STRETCH )

      stretch_sprite(out, o->brush.background, r.a.x, r.a.y, rect_sizex(r)+1, rect_sizey(r)+1);

    else

    if ( o->brush.state & BRUSH_CENTER ) {

      l_rect dx = (rect_sizex(r)-IMAGE_WIDTH(o->brush.background))/2;
      l_rect dy = (rect_sizey(r)-IMAGE_HEIGHT(o->brush.background))/2;

      rectfill(out, r.a.x, r.a.y, r.b.x, r.b.y, o->brush.color);

      draw_sprite(out, o->brush.background, r.a.x+dx, r.a.y+dy);

    } else

      blit_ex(o->brush.background, out, i.a.x, i.a.y, r.a.x, r.a.y,
              IMAGE_WIDTH(o->brush.background), IMAGE_HEIGHT(o->brush.background),
              rect_sizex(r)+1, rect_sizey(r)+1);

  } else {

    if (  o->brush.color == o->brush.color2 ||
        !(o->brush.state & BRUSH_GRADIENT) )

       rectfill(out, r.a.x, r.a.y, r.b.x, r.b.y, o->brush.color);

    else

       if ( o->brush.state & BRUSH_GRADIENT_HOR )

          fade_rect(out, r.a.x, r.a.y, r.b.x, r.b.y, o->brush.color, o->brush.color2, FR_HOR);

       else

          fade_rect(out, r.a.x, r.a.y, r.b.x, r.b.y, o->brush.color, o->brush.color2, FR_VER);

  };

};


t_rect scroller_scroll_limits ( p_scroller o )
{

  return VIEW(o)->size_limits(VIEW(o));

};


void   scroller_recalc_positions ( p_scroller o, l_long x, l_long y )
{
};


void   scroller_scroll_size ( p_scroller o, l_long *x, l_long *y )
{
  t_rect r = o->scroll_limits(o);

  if ( x ) *(x) = rect_sizex(r);
  if ( y ) *(y) = rect_sizey(r);

};


static l_bool self_rect ( t_rect r, p_view _this )
{

  p_view  p = _this;
  p_view  t = NULL;

  while ( p ) {

    t_rect v = r;

    v = rect_move(r, p->bounds.a.x, p->bounds.a.y);

    t = VIEW(OBJECT(p)->owner_view(OBJECT(p)));

    if ( t ) {

      t = VIEW(OBJECT(t)->first_view(OBJECT(t)));

      while ( t != p ) {

        if ( OBJECT(t)->is_state(OBJECT(t), OB_SF_VISIBLE) &&
             rect_overlay(t->bounds, v) )

          return false;

        t = VIEW(OBJECT(t)->next_view(OBJECT(t)));

      };

    };

    p = VIEW(OBJECT(p)->owner_view(OBJECT(p)));

  };

  return true;
};


/*
   scroll place.

   function scroll place of object (o), by delta x and delta y.

   dx - horizontal move
   dy - vertical move
   aft_move - if 0, than place is redraw now, if non-zero place is redraw
              when aft_move is set to 0, it only move coordinates. Then call
              scroll_place by 0, 0, SCROLL_NOW arguments. It's for
              slowly redrawing of place ( when accelerated functions
              of blitting are not support for video card ).

   - it also redraw horizontal and vertical scrollbars.

   - area to be scrolled is defined in scroll_limits function,
     that call size_limits function as default. (see t_view structure)

   - when object is scrolled, function recalc_positions is called for this
     object by arguments dx and dy. This function may set o->scrollx and
     o->scrolly to rounded values for specific object.

  - this function is supported in horizontal & vertical scrollbars.

*/

void   scroller_scroll_place ( p_scroller o, l_long dx, l_long dy, l_bool aft_move )
{
  t_rect  s;
  t_rect  t;
  l_long  sx;
  l_long  sy;
  l_long  maxx;
  l_long  maxy;

  l_long  old_scrollx = o->scrollx;
  l_long  old_scrolly = o->scrolly;

  p_view  p = NULL;

  if ( !dx && !dy && !o->aftmovex && !o->aftmovey ) return;

  o->scroll_size(o, &sx, &sy);
  o->max_moves(o, &maxx, &maxy);

  s = VIEW_CLIPED(o, o->scroll_limits(o));

  if ( o->scroll_auto & 0x01 )

     o->scrollx = lmax(0, lmin(maxx, o->scrollx+dx));

  else

     o->scrollx += dx;

  if ( o->scroll_auto & 0x02 )

     o->scrolly = lmax(0, lmin(maxy, o->scrolly+dy));

  else

     o->scrolly += dy;


  dx = o->scrollx - old_scrollx;

  dy = o->scrolly - old_scrolly;

  if ( !dx && !dy && !o->aftmovex && !o->aftmovey ) return;

  if ( aft_move ) { /* redraw after move */

    o->aftmovex += dx;
    o->aftmovey += dy;

    o->recalc_positions(o, dx, dy);

    if ( dx )

       VIEW(o->horbar)->draw_view(VIEW(o->horbar));

    if ( dy )

       VIEW(o->verbar)->draw_view(VIEW(o->verbar));

    return;

  } else {

    o->recalc_positions(o, dx, dy);

    if ( o->aftmovex ) dx = o->aftmovex;
    if ( o->aftmovey ) dy = o->aftmovey;

    o->aftmovex = 0;
    o->aftmovey = 0;

  };


  p = VIEW(OBJECT(o)->first_view(OBJECT(o)));

  while ( p ) {

    t = p->bounds;
    t = rect_move(t, -dx, -dy);

    p->set_bounds(p, t);

    p = VIEW(OBJECT(p)->next_view_to_last(OBJECT(p)));

  };

  if ( labs(dx) > rect_sizex(s) || labs(dy) > rect_sizey(s) ) {

    VIEW(o)->draw_in_rect(VIEW(o), s);

    if ( dx )

       VIEW(o->horbar)->draw_view(VIEW(o->horbar));

    if ( dy )

       VIEW(o->verbar)->draw_view(VIEW(o->verbar));

    return;

  };

  t = rect_move(s, -dx, -dy);

  if ( self_rect(s, VIEW(o)) ) {

     t_point pt = VIEW(o)->get_global_point(VIEW(o), point_assign(0, 0));

     t_rect  d = rect_assign(pt.x+s.a.x, pt.y+s.a.y, pt.x+s.b.x+1, pt.y+s.b.y+1);

     l_int   i = 0;
     l_int   i2 = 0;

     VIEW(o)->set_clips(VIEW(o), s);

     /* blit function */

     i  = mouse->block(mouse, d);

     blit(OUTBUFFER(VIEW(o)->draw_out), OUTBUFFER(VIEW(o)->draw_out), pt.x+s.a.x, pt.y+s.a.y, pt.x+t.a.x, pt.y+t.a.y, rect_sizex(s)+1, rect_sizey(s)+1);

     mouse->unblock(mouse, i);

     VIEW(o)->reset_clips(VIEW(o));

     rect_double_overlay(&t, &s);

     VIEW(o)->draw_in_rect(VIEW(o), t);
     VIEW(o)->draw_in_rect(VIEW(o), s);

  } else {

    TEST_SUB_VIEWS(o, VIEW(o)->draw_in_rect(VIEW(o), s));

  };

  if ( dx )

     VIEW(o->horbar)->draw_view(VIEW(o->horbar));

  if ( dy )

     VIEW(o->verbar)->draw_view(VIEW(o->verbar));

};


void   scroller_max_moves ( p_scroller o, l_long *dx, l_long *dy )
{
  t_rect l = o->scroll_limits(o);
  l_long sx = rect_sizex(l);
  l_long sy = rect_sizey(l);

  o->scroll_size(o, &sx, &sy);

  if ( dx ) *(dx) = calc_maxscrollx(o, sx-rect_sizex(l));
  if ( dy ) *(dy) = calc_maxscrolly(o, sy-rect_sizey(l));
};




/* hscrollbar */

/*
  object hscrollbar

  - this object is used for controling scroll boxes in horizontal coordinates.

  Arguments:

  r   - rect of hscrollbar, default height is STANDARD_SCROLLBAR_WIDTH defined
        in scroller.h file.

  f   - pointer to object, that scroll box. ( t_listbox, ... )

  If object is pressed to right, it run f->scroll_place(f, ax, 0, 0)
  function, where ax is f->deltax, if to the left ax is set to -f->deltax.

  note1 : dx and dy in scroll_place function is control by f->recalc_positions
          function for specific object. [ see dialogs.c ( t_listbox ) ]

  NOTE2:

  if you are using t_scroller initialization by (flag & SF_HORSCROLLBAR)
  this object is automatically added to window by f = pointer to your
  t_scroller.

*/

p_hscrollbar   _hscrollbar_init ( p_hscrollbar o, t_rect r, p_scroller f )
{
  if ( !o ) return NULL;

  clear_type(o, sizeof(t_hscrollbar));

  view_init(VIEW(o), r);


  /* object's functions */

  OBJECT(o)->translate_event = &hscrollbar_translate_event;


  /* view's functions */

  VIEW(o)->draw = &hscrollbar_draw;
  VIEW(o)->size_limits = &hscrollbar_size_limits;
  VIEW(o)->size_minimum = &hscrollbar_size_minimum;


  /* hscrollbar's functions and declarations */

  o->scroller = f;

  if ( scroll_after ) o->flags |= SBF_SCROLL_AFTER_MOVE;

  o->draw_bar = &hscrollbar_draw_bar;
  o->get_bar_size = &hscrollbar_get_bar_size;
  o->get_bar_pos = &hscrollbar_get_bar_pos;
  o->get_real_pos = &hscrollbar_get_real_pos;


  /* function calls */

  OBJECT(o)->set_options(OBJECT(o), OB_OF_SELECTABLE, false);

//  VIEW(o)->set_palette(VIEW(o), pal_scrollbar);

  VIEW(o)->brush.color = color_3d_face;
  VIEW(o)->brush.color2 = color_3d_shadow;
//  VIEW(o)->brush.skin = skin_hscrollbar;
  VIEW(o)->brush.state |= BRUSH_GRADIENT;

  return o;

};



/* vscrollbar */

/*
  object vscrollbar

  - this object is used for controling scroll boxes in horizontal coordinates.

  Arguments:

  r   - rect of vscrollbar, default width is STANDARD_SCROLLBAR_WIDTH defined
        in scroller.h file.

  f   - pointer to object, that scroll box. ( t_listbox, ... )

  If object is pressed up, it run f->scroll_place(f, 0, ay, 0)
  function, where ay is f->deltay, if down ay is set to -f->deltay.

  note1 : dx and dy in scroll_place function is control by f->recalc_positions
          function for specific object. [ see dialogs.c ( t_listbox ) ]

  NOTE2:

  if you are using t_scroller initialization by (flag & SF_VERSCROLLBAR)
  this object is automatically added to window by f = pointer to your
  t_scroller.

*/
p_vscrollbar   _vscrollbar_init ( p_vscrollbar o, t_rect r, p_scroller f )
{
  if ( !o ) return NULL;

  clear_type(o, sizeof(t_vscrollbar));

  view_init(VIEW(o), r);


  /* object's functions */

  OBJECT(o)->translate_event = &vscrollbar_translate_event;


  /* view's functions */

  VIEW(o)->draw = &vscrollbar_draw;
  VIEW(o)->size_limits = &vscrollbar_size_limits;
  VIEW(o)->size_minimum = &vscrollbar_size_minimum;


  /* vscrollbar's functions and declarations */

  o->scroller = f;
  if ( scroll_after ) o->flags |= SBF_SCROLL_AFTER_MOVE;

  o->draw_bar = &vscrollbar_draw_bar;
  o->get_bar_size = &vscrollbar_get_bar_size;
  o->get_bar_pos = &vscrollbar_get_bar_pos;
  o->get_real_pos = &vscrollbar_get_real_pos;


  /* function calls */

  OBJECT(o)->set_options(OBJECT(o), OB_OF_SELECTABLE, false);

//  VIEW(o)->set_palette(VIEW(o), pal_scrollbar);

  VIEW(o)->brush.color = color_3d_face;
  VIEW(o)->brush.color2 = color_3d_shadow;
//  VIEW(o)->brush.skin = skin_vscrollbar;
  VIEW(o)->brush.state |= BRUSH_GRADIENT+BRUSH_GRADIENT_HOR;

  return o;

};



/* scroller */

p_scroller   _scroller_init ( p_scroller o, t_rect r, l_int flags )
{

  if ( !o ) return NULL;

  clear_type(o, sizeof(t_scroller));

  view_init(VIEW(o), r);

  /* object's functions */

  OBJECT(o)->setup = &scroller_setup;
  OBJECT(o)->done = &scroller_done;


  /* view's functions */

  VIEW(o)->background = &scroller_background;
  VIEW(o)->change_bounds = &scroller_change_bounds;


  /* scroller's functions and declarations */

  o->scrollx = 0;
  o->scrolly = 0;
  o->deltax = 5;
  o->deltay = 5;

  o->flags  = flags;

  o->scroll_auto = 0x03;

  o->scroll_limits = &scroller_scroll_limits;
  o->scroll_size = &scroller_scroll_size;
  o->scroll_place = &scroller_scroll_place;
  o->max_moves = &scroller_max_moves;
  o->recalc_positions = &scroller_recalc_positions;

  return o;

};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?