scroller.c

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

C
1,223
字号
/******************************************************************
 * SEAL 2.0                                                       *
 * Copyright (c) 1999-2002 SEAL Developers. All Rights Reserved.  *
 *                                                                *
 * Web site: http://sealsystem.sourceforge.net/                   *
 * E-mail (current maintainer): orudge@users.sourceforge.net      *
 ******************************************************************/

/*
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <seal.h>
#include <scroller.h>
#include <math.h>

l_bool   scroll_after = false;

/*
0 3d_face="200, 200, 200"
1 3d_light="255, 255, 255"
2 3d_shadow="128, 128, 128"
3 3d_dark="32, 32, 32"
*/

p_scroller   (*scroller_init) ( p_scroller o, t_rect r, l_int flags ) = &_scroller_init;
p_vscrollbar (*vscrollbar_init) ( p_vscrollbar o, t_rect r, p_scroller f ) = &_vscrollbar_init;
p_hscrollbar (*hscrollbar_init) ( p_hscrollbar o, t_rect r, p_scroller f ) = &_hscrollbar_init;


/* vscrollbar functions */

void   vscrollbar_translate_event ( p_object o, t_event *event )
{

  p_vscrollbar vsb = VSCROLLBAR(o);

  RETVIEW(o, event);

  view_translate_event(o, event);

  if ( !vsb->scroller && vsb->scroller->deltax <= 0 )

    return; /* if hasn't scroller or deltax <= 0 */

  if ( event->type & EV_MOUSE && OBJECT(mouse)->state & MO_SF_MOUSELDOWN ) {

      p_scroller   scr = SCROLLER(vsb->scroller);
      p_vscrollbar so = VSCROLLBAR(o);
      t_point ml   = VIEW(o)->get_local_point(VIEW(o), mouse->where);
      t_rect  s    = VIEW(o)->size_limits(VIEW(o));
      l_rect  size = vsb->get_bar_size(vsb);
      l_rect  pos  = vsb->get_bar_pos(vsb);
      l_long  maxy = 0;

      scr->max_moves(scr, 0, &maxy);

      if ( ml.y > pos && ml.y < pos + STANDARD_SCROLLBUTTON_SIZE ) { /* UP scrolling by 1 */

        /* UP scrolling by 1*/

        #define ok_scroll_up ((OBJECT(mouse)->state & MO_SF_MOUSELPRESS) && (scr->scrolly > 0))

        while ( ok_scroll_up ) {

          l_rect   pos_mouse;
          t_point  p;

          scr->scroll_place(scr, 0, -scr->deltay, (vsb->flags & SBF_SCROLL_AFTER_MOVE));  /* up scrolling */

          clear_event(event);

          o->get_event(o, event); /* get events */

          if ( !ok_scroll_up )

             scr->scroll_place(scr, 0, 0, SCROLL_NOW); /* scroll if SBF_SCROLL_AFTER_MOVE is set */

          pos_mouse  = vsb->get_bar_pos(vsb)+(STANDARD_SCROLLBUTTON_SIZE/2);
          p  = point_assign(s.a.x+rect_sizex(s)/2, pos_mouse);

          mouse->set_pos(mouse, VIEW(o)->get_global_point(VIEW(o), p));

        };

      } else

      if ( ml.y < pos + size &&
           ml.y > pos + size - STANDARD_SCROLLBUTTON_SIZE ) { /* DOWN scrolling by 1 */

        /* DOWN scrolling by 1*/

        #define ok_scroll_down ((OBJECT(mouse)->state & MO_SF_MOUSELPRESS) && (scr->scrolly < maxy))

        while ( ok_scroll_down ) {

          l_rect   size;
          l_rect   pos_mouse;
          t_point  p;

          scr->scroll_place(scr, 0, scr->deltay, (vsb->flags & SBF_SCROLL_AFTER_MOVE)); /* down scrolling */

          clear_event(event);

          o->get_event(o, event); /* get events */

          if ( !ok_scroll_down )

             scr->scroll_place(scr, 0, 0, SCROLL_NOW); /* scroll if SBF_SCROLL_AFTER_MOVE is set */

          size = vsb->get_bar_size(vsb);
          pos_mouse  = vsb->get_bar_pos(vsb)+size-(STANDARD_SCROLLBUTTON_SIZE/2);
          p  = point_assign(s.a.x+rect_sizex(s)/2, pos_mouse);

          mouse->set_pos(mouse, VIEW(o)->get_global_point(VIEW(o), p));

        };

      } else

      if ( ml.y > pos + STANDARD_SCROLLBUTTON_SIZE &&
           ml.y < pos + size - STANDARD_SCROLLBUTTON_SIZE ) { /* 2 sides scrolling */

         l_rect  oldy = ml.y;

         /* UPDOWN scrolling */

         #define ok_scroll_updown (!(OBJECT(mouse)->state & MO_SF_MOUSELUP))

         while ( ok_scroll_updown ) {

            if ( ml.y != oldy ) {  /*  */

                  scr->scroll_place(scr, 0, so->get_real_pos(so, ml.y)-so->get_real_pos(so, oldy), (vsb->flags & SBF_SCROLL_AFTER_MOVE));

            };

            oldy = ml.y;

            o->get_event(o, event); /* get events */

            if ( !ok_scroll_updown ) /* scroll after */

                  scr->scroll_place(scr, 0, 0, SCROLL_NOW); /* scroll if SBF_SCROLL_AFTER_MOVE is set */

            ml = VIEW(o)->get_local_point(VIEW(o), mouse->where);

         };

      };

  };

};


t_rect vscrollbar_size_limits ( p_view o )
{

  t_rect r = o->get_local_extent(o);

  return rect_assign(r.a.x+1, r.a.y+1, r.b.x-1, r.b.y-1);

};


t_point vscrollbar_size_minimum ( p_view o )
{

  return point_assign(MINIMUM_SCROLLBAR_WIDTH, MINIMUM_SCROLLBAR_SIZE);

};


void   vscrollbar_draw ( p_view o )
{
  t_rect  r = o->get_local_extent(o);
  t_point p;

  BITMAP *out = o->begin_paint(o, &p, r);

  if ( out ) {

    o->background(o, out, rect_move(r, p.x, p.y));

    rectfill(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, color_3d_face);
    // light_image ( out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, 20, 20, 20);
     button(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, color_3d_shadow, color_3d_light);

    VSCROLLBAR(o)->draw_bar(VSCROLLBAR(o));

  };

  o->end_of_paint(o, r);
};


void   vscrollbar_draw_bar ( p_vscrollbar o )
{
  p_view  vo = VIEW(o);
  t_rect  r = vo->size_limits(vo);
  t_rect  s = r;
  t_point p;

  l_rect  pos  = o->get_bar_pos(o);
  l_rect  size = o->get_bar_size(o);

  BITMAP *out;

  r = rect_assign(r.a.x, r.a.y+pos, r.b.x, min(r.b.y, r.a.y+pos+size));

  out = vo->begin_paint(vo, &p, r);

  if ( out ) {

    l_color bcolor = color_3d_face;

    l_int   minush = 8;
    l_int   plush  = 8;
    GrFONT *font   = get_font_in_size("Symbols", 8, 8);

    //if (!vo->brush.skin) {
      rectfill(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, bcolor);

      button( out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, color_3d_light, color_3d_shadow);


      draw_double_text(out, font, "f", -1, r.a.x+p.x+1, r.a.y+p.y,
                       r.b.x+p.x, r.a.y+p.y+minush, TX_ALIGN_CENTER, color_3d_light, color_3d_shadow, 0);

      draw_double_text(out, font, "g", -1, r.a.x+p.x+1, r.b.y+p.y-plush,
                       r.b.x+p.x, r.b.y+p.y, TX_ALIGN_CENTER, color_3d_light, color_3d_shadow, 0);
    /*} else {
      blit(VIEW(o)->brush.skin, out, 0, 0, r.a.x+p.x, r.a.y+p.y, 15, 10);
      stretch_blit(VIEW(o)->brush.skin, out, 0, 10, 15, 10, r.a.x+p.x, r.a.y+p.y+10, 15, rect_sizey(r)-19);
      blit(VIEW(o)->brush.skin, out, 0, 20, r.a.x+p.x, r.b.y+p.y-9, 15, 10);
    };*/

  };

  vo->end_of_paint(vo, r);
};


l_rect vscrollbar_get_bar_size ( p_vscrollbar o )
{

  if ( o->scroller ) {

    l_rect  sizey = rect_sizey(VIEW(o)->size_limits(VIEW(o)));
    l_rect  sizey_scroller = rect_sizey(o->scroller->scroll_limits(o->scroller));
    l_long  maxy = 0;
    l_rect  size;

    o->scroller->scroll_size(o->scroller, NULL, &maxy);

    size = lmax(MINIMUM_SCROLLBOX_SIZE, (l_rect)((double)sizey*((double)sizey_scroller/(double)(lmax(1, maxy)))));

    return size;

  };

  return 0;

};


l_long  vscrollbar_get_real_pos ( p_vscrollbar o, l_rect pos )
{
  l_long i = 0;
  l_long m_x = 0;
  l_long m_y = 0;
  t_rect s = VIEW(o)->size_limits(VIEW(o));

  if ( !o->scroller ) return i;

  o->scroller->scroll_size(o->scroller, &m_x, &m_y);

  if ( rect_sizey(s) && m_y ) {

    double y = ((double)m_y / (double)max(1, rect_sizey(s))) * (double)pos;

    y = (ceil(y / max(1, o->scroller->deltay))*o->scroller->deltay);

    i = (l_long)y;

  };

  return i;

};


l_rect vscrollbar_get_bar_pos ( p_vscrollbar o )
{

  if ( o->scroller ) {

    l_rect  sizey = rect_sizey(VIEW(o)->size_limits(VIEW(o)));
    l_rect  sizey_scroller = rect_sizey(o->scroller->scroll_limits(o->scroller));
    l_long  maxy = 0;
    l_long  sy = o->scroller->scrolly;
    l_rect  pos;
    l_rect  size;
    l_int   dy = 0;

    o->scroller->scroll_size(o->scroller, NULL, &maxy);

    size = (l_rect)((double)sizey*((double)sizey_scroller/(double)(lmax(1, maxy))));

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

    pos = (l_rect)((double)(sizey-dy)*((double)sy/(double)(max(1, maxy))));

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

    return pos;

  };

  return 0;

};



/* hscrollbar functions */

void   hscrollbar_translate_event ( p_object o, t_event *event )
{

  p_hscrollbar hsb = HSCROLLBAR(o);

  RETVIEW(o, event);

  view_translate_event(o, event);

  if ( !hsb->scroller && hsb->scroller->deltax <= 0 )

    return; /* if hasn't scroller or deltax <= 0 */

  if ( event->type & EV_MOUSE && OBJECT(mouse)->state & MO_SF_MOUSELDOWN ) {

      p_scroller scr = SCROLLER(hsb->scroller);
      p_hscrollbar so = HSCROLLBAR(o);
      t_point ml   = VIEW(o)->get_local_point(VIEW(o), mouse->where);
      t_rect  s    = VIEW(o)->size_limits(VIEW(o));
      l_rect  size = hsb->get_bar_size(hsb);
      l_rect  pos  = hsb->get_bar_pos(hsb);
      l_long  maxx = 0;

      scr->max_moves(scr, &maxx, 0);

      if ( ml.x > pos && ml.x < pos + STANDARD_SCROLLBUTTON_SIZE ) { /* LEFT scrolling by 1 */

        /* LEFT scrolling by 1*/

        #define ok_scroll_left ((OBJECT(mouse)->state & MO_SF_MOUSELPRESS) && (scr->scrollx > 0))

        while ( ok_scroll_left ) {

          l_rect   pos_mouse;
          t_point  p;

          scr->scroll_place(scr, -scr->deltax, 0, (hsb->flags & SBF_SCROLL_AFTER_MOVE));  /* left scrolling */

          clear_event(event);

          o->get_event(o, event); /* get events */

          if ( !ok_scroll_left )

             scr->scroll_place(scr, 0, 0, SCROLL_NOW); /* scroll if SBF_SCROLL_AFTER_MOVE is set */

          pos_mouse  = hsb->get_bar_pos(hsb)+(STANDARD_SCROLLBUTTON_SIZE/2);
          p  = point_assign(pos_mouse, s.a.y+rect_sizey(s)/2);

          mouse->set_pos(mouse, VIEW(o)->get_global_point(VIEW(o), p));

        };

      } else

      if ( ml.x < pos + size &&
           ml.x > pos + size - STANDARD_SCROLLBUTTON_SIZE ) { /* RIGHT scrolling by 1 */

        /* RIGHT scrolling by 1*/

        #define ok_scroll_right ((OBJECT(mouse)->state & MO_SF_MOUSELPRESS) && (scr->scrollx < maxx))

        while ( ok_scroll_right ) {

          l_rect   size;
          l_rect   pos_mouse;
          t_point  p;

          scr->scroll_place(scr, scr->deltax, 0, (hsb->flags & SBF_SCROLL_AFTER_MOVE)); /* right scrolling */

          clear_event(event);

          o->get_event(o, event); /* get events */

          if ( !ok_scroll_right )

             scr->scroll_place(scr, 0, 0, SCROLL_NOW); /* scroll if SBF_SCROLL_AFTER_MOVE is set */

          size = hsb->get_bar_size(hsb);
          pos_mouse  = hsb->get_bar_pos(hsb)+size-(STANDARD_SCROLLBUTTON_SIZE/2);
          p  = point_assign(pos_mouse, s.a.y+rect_sizey(s)/2);

          mouse->set_pos(mouse, VIEW(o)->get_global_point(VIEW(o), p));

        };

      } else

      if ( ml.x > pos + STANDARD_SCROLLBUTTON_SIZE &&
           ml.x < pos + size - STANDARD_SCROLLBUTTON_SIZE ) { /* 2 sides scrolling */

         l_rect oldx = ml.x;

         /* LEFTRIGHT scrolling */

         #define ok_scroll_leftright (!(OBJECT(mouse)->state & MO_SF_MOUSELUP))

         while ( ok_scroll_leftright ) {

            if ( ml.x != oldx ) {  /*  */

                  scr->scroll_place(scr, so->get_real_pos(so, ml.x)-so->get_real_pos(so, oldx), 0, (hsb->flags & SBF_SCROLL_AFTER_MOVE));

            };

            oldx = ml.x;

            o->get_event(o, event); /* get events */

            if ( !ok_scroll_leftright ) /* scroll after */

                  scr->scroll_place(scr, 0, 0, SCROLL_NOW); /* scroll if SBF_SCROLL_AFTER_MOVE is set */

            ml = VIEW(o)->get_local_point(VIEW(o), mouse->where);

         };

      };

  };

};


t_rect hscrollbar_size_limits ( p_view o )
{

  t_rect r = o->get_local_extent(o);

  return rect_assign(r.a.x+1, r.a.y+1, r.b.x-1, r.b.y-1);

};


t_point hscrollbar_size_minimum ( p_view o )
{

  return point_assign(MINIMUM_SCROLLBAR_SIZE, MINIMUM_SCROLLBAR_WIDTH);

};


void   hscrollbar_draw ( p_view o )
{
  t_rect  r = o->get_local_extent(o);
  t_point p;

  BITMAP *out = o->begin_paint(o, &p, r);

  if ( out ) {

    o->background(o, out, rect_move(r, p.x, p.y));

    rectfill(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, color_3d_face);

    button(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, color_3d_shadow, color_3d_light);

    HSCROLLBAR(o)->draw_bar(HSCROLLBAR(o));

  };

  o->end_of_paint(o, r);
};


void   hscrollbar_draw_bar ( p_hscrollbar o )
{
  p_view  vo = VIEW(o);
  t_rect  r = vo->size_limits(vo);
  t_point p;

  l_rect  pos  = o->get_bar_pos(o);
  l_rect  size = o->get_bar_size(o);

  BITMAP *out;

  r = rect_assign(r.a.x+pos, r.a.y, min(r.b.x, r.a.x+pos+size), r.b.y);

  out = vo->begin_paint(vo, &p, r);

  if ( out ) {

    l_color bcolor = color_3d_face;

    GrFONT *font   = get_font_in_size("Symbols", 8, 8);
    l_int   minusw = FONT_GETWIDTH(font, '!');
    l_int   plusw  = FONT_GETWIDTH(font, '"');

    if ( plusw > minusw ) minusw = plusw;

   // if (!vo->brush.skin) {
      rectfill(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, bcolor);

      button(out, r.a.x+p.x, r.a.y+p.y, r.b.x+p.x, r.b.y+p.y, color_3d_light, color_3d_shadow);


      draw_double_text(out, font, "e", -1, r.a.x+p.x, r.a.y+p.y,
                       r.a.x+p.x+minusw+1, r.b.y+p.y, TX_ALIGN_CENTER, color_3d_light, color_3d_shadow, 0);

      draw_double_text(out, font, "b", -1, r.b.x+p.x-plusw-1, r.a.y+p.y,
                       r.b.x+p.x, r.b.y+p.y, TX_ALIGN_CENTER, color_3d_light, color_3d_shadow, 0);
  /*  } else {
      blit(vo->brush.skin, out, 0, 0, r.a.x+p.x, r.a.y+p.y, 10, 15);
      stretch_blit(vo->brush.skin, out, 10, 0, 10, 15, r.a.x+p.x+10, r.a.y+p.y, rect_sizex(r)-19, 15);
      blit(vo->brush.skin, out, 20, 0, r.b.x+p.x-9, r.a.y+p.y, 10, 15);
    };*/

  };

  vo->end_of_paint(vo, r);
};


l_rect hscrollbar_get_bar_size ( p_hscrollbar o )
{
  if ( o->scroller ) {

    l_rect  sizex = rect_sizex(VIEW(o)->size_limits(VIEW(o)));
    l_rect  sizex_scroller = rect_sizex(o->scroller->scroll_limits(o->scroller));
    l_long  maxx;
    l_rect  size;

    o->scroller->scroll_size(o->scroller, &maxx, NULL);

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

    return size;

  };

  return 0;

};


l_long  hscrollbar_get_real_pos ( p_hscrollbar o, l_rect pos )
{
  l_long i = 0;
  l_long m_x = 0;
  l_long m_y = 0;
  t_rect s = VIEW(o)->size_limits(VIEW(o));

  if ( !o->scroller ) return i;

  o->scroller->scroll_size(o->scroller, &m_x, &m_y);

  if ( rect_sizex(s) && m_x ) {

    double x = ((double)m_x / max(1, (double)rect_sizex(s))) * (double)pos;

    x = (ceil(x / max(1, o->scroller->deltax))*o->scroller->deltax);

    i = (l_long)x;

  };

  return i;
};


l_rect hscrollbar_get_bar_pos ( p_hscrollbar o )
{

  if ( o->scroller ) {

    l_rect  sizex = rect_sizex(VIEW(o)->size_limits(VIEW(o)));
    l_rect  sizex_scroller = rect_sizex(o->scroller->scroll_limits(o->scroller));
    l_long  maxx;
    l_rect  pos;
    l_rect  size;
    l_int   dx = 0;

⌨️ 快捷键说明

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