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 + -
显示快捷键?