home *** CD-ROM | disk | FTP | other *** search
- // ____________________________________________________
- // | |
- // | Project: POWER VIEW INTERFACE |
- // | File: PVITEMS.CPP |
- // | Compiler: WPP386 (10.6) |
- // | |
- // | Subject: Base class for PV items |
- // | |
- // | Author: Emil Dotchevski |
- // |____________________________________________________|
- //
- // E-mail: zajo@geocities.com
- // URL: http://www.geocities.com/SiliconValley/Bay/3577
-
- #define uses_app
- #define uses_colors
- #define uses_dc
- #define uses_desk
- #define uses_help
- #define uses_system
-
- #define DECLARE_PVITEMS
- #include "PVuses.h"
- #undef DECLARE_PVITEMS
-
- #ifndef NOHELP
- static uint help_context = 0;
- #endif
- static void *command_information = NULL;
- static uint command_size = 0;
-
- boolean is_valid( Titem *item )
- {
- if( ( item != NULL ) && item->valid( cmVALID ) ) return 1;
- DELETE( item );
- return 0;
- }
-
- #ifndef NOHELP
- void _help( uint hlp_ctx )
- {
- if( !help_context ) help_context = hlp_ctx;
- }
-
- uint __help( void )
- {
- uint h;
-
- h = help_context;
- help_context = 0;
- return h;
- }
- #endif
-
- void _command_info( void *cmd_info, uint cmd_size )
- {
- command_information = cmd_info;
- command_size = cmd_size;
- }
-
- Titem *message( Titem *receiver, uint command )
- {
- if( receiver != NULL )
- return receiver->handle_command( receiver, command );
- else
- return NULL;
- }
-
- Titem *broadcast( uint command )
- {
- return application->handle_command( NULL, command );
- }
-
- Titem *modal_broadcast( uint command )
- {
- if( modal_item != NULL )
- return modal_item->handle_command( NULL, command );
- else
- return NULL;
- }
-
- //Titem publics:
-
- /*
- Description:
- Construct item with given bounds.
- Entry:
- _xl, _yl: item width,heigh.
- */
- Titem::Titem( int _xl, int _yl )
- {
- flags_word = ifVISIBLE+ifSELECTABLE+ifCLOSEABLE+ifMOVABLE+ifRESIZEABLE+ifTAB_STOP;
- state_word = 0;
- event_mask = evCOMMAND+evKEYBOARD;
- #ifndef NOMOUSE
- event_mask |= evMOUSE_DOWN+evMOUSE_UP+evMOUSE_DRAG;
- #endif
- next = NULL;
- owner = NULL;
- last = NULL;
- current = NULL;
- bound_x = x = 0;
- bound_y = y = 0;
- bound_xl = xl = _xl;
- bound_yl = yl = _yl;
- curs_x = 0;
- curs_y = 0;
- curs_type = 0;
- grow_mode = gmDONT_GROW;
- drag_mode = dmDONT_DRAG;
- #ifndef NOHELP
- help_ctx = __help();
- #endif
- drop_id = 0;
- stop_state = 0;
- backgrnd_attr = 0;
- backgrnd_char = ' ';
- items_changed = 0;
- set_state( isVALID+isACTIVE, 1 );
- }
-
- /*
- Description:
- Dispose all subitems. Exclude self from the owner's list.
- */
- Titem::~Titem( void )
- {
- while( last != NULL )
- if( last->flags( ifSTAY ) )
- remove( last );
- else
- DELETE( last );
- if( owner != NULL ) owner->remove( this );
- cancel_update( this );
- }
-
- /*
- Description:
- Returns pointer to the first (topmost) sub-item, or NULL.
- */
- Titem *Titem::first( void )
- {
- if( last != NULL )
- return last->next;
- else
- return NULL;
- }
-
- /*
- Description:
- Returns pointer to the previous sub-item in the owner's list (circular),
- or NULL if item has no owner;
- */
- Titem * Titem::prev( void )
- {
- Titem *p;
-
- if( owner == NULL )
- return NULL;
- else
- {
- p = this;
- while( p->next != this)
- {
- p = p->next;
- }
- return p;
- }
- }
-
- /*
- Description:
- Returns pointer to the next sub-item in the owner's list (linear),
- or NULL if it is the last item, or has no owner;
- */
- Titem * Titem::nextl( void )
- {
- if( ( owner == NULL ) || ( owner->last == this ) )
- return NULL;
- else
- return next;
- }
-
- /*
- Description:
- Returns pointer to the previous sub-item in the owner's list (linear),
- or NULL if it is the first item, or has no owner;
- */
- Titem * Titem::prevl( void )
- {
- if( ( owner == NULL ) || ( owner->first() == this ) )
- return NULL;
- else
- return prev();
- }
-
- /*
- Description:
- Set or clear flags_word bits depending on 'enable'. Handle some special
- cases. Can be overriden to handle more special cases.
- Entry:
- _flags_word: requested bit mask;
- enable: 1 - set bits, 0 - clear.
- */
- void Titem::set_flags( uint _flags_word, boolean enable )
- {
- uint f;
-
- if( ( _flags_word & ifSELECTABLE ) && !enable && state( isSELECTED ) )
- {
- set_state( isSELECTED, 0 );
- if( state( isSELECTED ) ) _flags_word &= ~ifSELECTABLE;
- }
- f = flags_word;
- if( enable )
- flags_word |= _flags_word;
- else
- flags_word &= ~_flags_word;
- if( ( f != flags_word ) && ( _flags_word & ifVISIBLE ) ) redraw();
- }
-
- /*
- Description:
- Set or clear state bits depending on 'enable'. Handle some special
- cases. Can be overriden to handle more special cases.
- Entry:
- _state_word: requested bit mask;
- enable: 1 - set bits, 0 - clear.
- */
- void Titem::set_state( uint _state_word, boolean enable )
- {
- uint s, ns;
- boolean f;
- Titem *p;
-
- if( enable )
- {
- if( ( _state_word & isACTIVE ) &&
- flags( ifSELECTABLE ) && !state( isSELECTED ) )
- _state_word &= ~isACTIVE;
- if( ( _state_word & isACCESSABLE ) && !event_mask )
- _state_word &= ~isACCESSABLE;
- if( ( _state_word & isALIVE ) && ( !flags( ifVISIBLE ) || state( isHIDDEN ) ) )
- _state_word &= ~isALIVE;
- if( ( _state_word & isSELECTED ) &&
- ( !flags(ifSELECTABLE) || owner==NULL ||
- ( ( ( p = owner->current ) != NULL ) &&
- ( p->set_state( isSELECTED, 0 ),
- p->state( isSELECTED )
- )
- )
- )
- )
- _state_word &= ~isSELECTED;
- }
- else
- if( ( _state_word & isSELECTED ) && state( isFOCUSED ) && !release_focus() )
- _state_word &= ~isSELECTED;
- if( enable ) ns = state_word | _state_word; else ns = state_word & ~_state_word;
- if( state_word == ns ) return;
- s = _state_word & ( isACTIVE+isALIVE+isDISABLED+isACCESSABLE );
- if( s )
- for( p=first(); p!=NULL; p=p->nextl() )
- p->set_state( s, enable );
- f = ( ( _state_word & ( isFOCUSED+isSELECTED+isDISABLED+isHIDDEN ) ) != 0 );
- if( f ) redraw();
- s = state_word; state_word = ns;
- if( ( state_word & isHIDDEN ) != ( s & isHIDDEN ) )
- {
- set_state( isALIVE, !enable && owner && owner->state( isALIVE ) );
- if( owner != NULL )
- if( enable )
- req_update( owner );
- else
- owner->update_bounds( this );
- }
- if( ( state_word & isDISABLED ) != ( s & isDISABLED ) )
- set_state( isACTIVE, !enable );
- if( ( state_word & isSELECTED ) != ( s & isSELECTED ) )
- {
- set_state( isACTIVE, enable );
- if( owner != NULL )
- if( enable )
- {
- owner->current = this;
- p = owner;
- while( ( p != modal_item ) && ( p->owner != NULL ) && ( p->owner->current == p ) )
- p = p->owner;
- if( p == modal_item ) set_state( isFOCUSED, 1 );
- }
- else
- {
- owner->current = NULL;
- set_state( isFOCUSED, 0 );
- }
- }
- if( ( state_word & isFOCUSED ) != ( s & isFOCUSED ) )
- {
- if( enable ) get_focused();
- if( current != NULL ) current->set_state( isFOCUSED, enable );
- }
- if( f ) redraw();
- if( ( state_word & isMODAL ) != ( s & isMODAL ) )
- {
- set_state( isACCESSABLE, enable );
- if( enable ) set_state( isACTIVE, 1 );
- }
- if( ( _state_word & isON_TOP ) && owner )
- if( enable )
- owner->pop_item( this );
- else
- owner->do_pop_top_items( owner->last );
- }
-
- /*
- Description:
- Test state of the item's owner just before desktop or application.
- Usually used to determine is the window that (indirectly) owns the
- item active, selected, and so on.
- */
- boolean Titem::window_state( uint _state_word )
- {
- Titem *p;
-
- p = this;
- while( p->owner != NULL )
- {
- if( ( p->owner == desktop ) || ( p->owner == application ) )
- return p->state( _state_word );
- p = p->owner;
- }
- return 0;
- }
-
- /*
- Description:
- Focus the item. Returns 0 if not successfull. This may be because
- another item do not release the focus.
- */
- boolean Titem::focus( void )
- {
- if( state(isDISABLED) ) return 0;
- if( ( owner == NULL ) || state( isFOCUSED|isMODAL ) ) return 1;
- if( owner->focus() )
- {
- set_state( isSELECTED, 1 );
- return state( isSELECTED );
- }
- return 0;
- }
-
- /*
- Description:
- Called when item is mouse-clicked. Original pop_up does nothing but
- calls owner's pop_up.
- */
- void Titem::pop_up( void )
- {
- if( owner != NULL ) owner->pop_up();
- }
-
- /*
- Description:
- Select next or previous tabstop item, depending on direction.
- */
- void Titem::tab_next( int direction )
- {
- Titem *p;
- boolean ts, dis, tab;
-
- if( ( last == NULL ) || ( current == NULL ) ) return;
- ts = 0;
- p = current;
- do
- {
- if( direction>0 ) p = p->next; else p = p->prev();
- dis = p->state( isDISABLED );
- tab = p->flags( ifTAB_STOP );
- if( tab ) ts = dis;
- }
- while( ( !p->flags( ifSELECTABLE ) || !p->state( isALIVE ) || dis || (!tab && !ts) ) && ( p != current ) );
- if( p != current ) p->focus();
- }
-
- /*
- Description:
- Select next or previous item (depending on direction) between two
- tabstop items.
- */
- void Titem::local_next( int direction )
- {
- Titem *p;
-
- if( ( last == NULL ) || ( current == NULL ) || ( ( direction>0 ) && ( current->flags( ifTAB_STOP ) ) ) ) return;
- p = current;
- do
- {
- if( direction>0 ) p = p->next; else p = p->prev();
- }
- while( ( !p->flags( ifSELECTABLE ) || !p->state( isALIVE ) || p->state( isDISABLED ) ) && ( p != current ) );
- if( ( p != current ) && ( ( direction>0 ) || !p->flags( ifTAB_STOP ) ) ) p->focus();
- }
-
- /*
- Description:
- Modify item events mask.
- Entry:
- mask: events to modify;
- enable: 1 - enable events, 0 - disable.
- */
- void Titem::set_events_mask( uint mask, boolean enable )
- {
- if( enable )
- {
- event_mask |= mask;
- application->or_events_mask( this );
- }
- else
- {
- event_mask &= ~mask;
- application->update_events_mask();
- }
- }
-
- /*
- Description:
- Drag item to to a new location (based on the owner's coordinates).
- Can be overriden to limit item drag region.
- Entry:
- _x, _y: requested new position.
- */
- void Titem::drag( int _x, int _y )
- {
- redraw();
- x = _x; y = _y;
- redraw();
- if( owner != NULL ) owner->update_bounds( this );
- }
-
- /*
- Description:
- Resize item to a new bounds. Can be overriden to limit item bounds.
- Entry:
- _xl, _yl: requested new width, heigh.
- */
- void Titem::resize( int _xl, int _yl )
- {
- Titem *p;
- int old_xl, old_yl;
-
- redraw();
- old_xl = xl; old_yl = yl;
- xl = _xl; yl = _yl;
- p = first();
- while( p != NULL )
- {
- p->calc_bounds( xl - old_xl, yl - old_yl );
- p = p->nextl();
- }
- redraw();
- optimize_bounds();
- }
-
- /*
- Description:
- Translate global coordinates to item's local coordinates.
- Entry:
- x1, y1: global coordinates.
- Exit:
- x2, y2: local coordinates.
- */
- void Titem::make_local( int x1, int y1, int &x2, int &y2 )
- {
- Titem *p;
-
- x2 = x1; y2 = y1;
- p = this;
- while( p != NULL )
- {
- x2 -= p->x; y2 -= p->y;
- p = p->owner;
- }
- }
-
- /*
- Description:
- Translate local coordinates to global screen coordinates.
- Entry:
- x1, y1: local coordinates.
- Exit;
- x2, y2: global coordinates.
- */
- void Titem::make_global( int x1, int y1, int &x2, int &y2 )
- {
- Titem *p;
-
- x2 = x1; y2 = y1;
- p = this;
- while( p != NULL )
- {
- x2 += p->x; y2 += p->y;
- p = p->owner;
- }
- }
-
- /*
- Description:
- Returns global coordinates of the item's upper-left corner.
- Exit:
- _x, _y: global item coordinates.
- */
- void Titem::get_origin( int &_x, int &_y )
- {
- make_global( 0, 0, _x, _y );
- }
-
- /*
- Description:
- Determine if the point given by it's global coordinates is inside the
- item. Can be overriden to handle items with a strange form, instead of
- a rectangle.
- Entry:
- _x, _y: global point coordinates.
- Exit:
- 1: point is inside the item, 0 - otherwise.
- */
- boolean Titem::check_inside( int _x, int _y )
- {
- int a, b;
-
- get_origin( a, b );
- return ( _x >= a ) && ( _x < ( a + xl ) ) &&
- ( _y >= b ) && ( _y < ( b + yl ) );
- }
-
- /*
- Description:
- Invalidate item rectangle, cousing item (or it's buffer, if item is
- buffered) to be redrawn during next screen update loop.
- */
- void Titem::redraw( void )
- {
- int a, b;
-
- if( !state( isALIVE ) ) return;
- get_origin( a, b );
- screen_dc->invalidate( a + bound_x, b + bound_y, bound_xl, bound_yl );
- }
-
- /*
- Description:
- If message can be handled by the item, handle_event calls event_handler
- and, after that handles some special cases.
- Note:
- if a command message successfully handled, and if info isn't NULL, and
- size isn't 0, then command info is disposed.
- Entry:
- ev: event to be handled.
- */
- void Titem::handle_event( Tevent &ev )
- {
- Titem *p;
- Titem *c;
-
- if( ( last != NULL ) && ( !state( isICONIZED ) || ev.code==evCOMMAND ) )
- {
- items_changed = 0;
- p = first();
- while( p != NULL )
- {
- if( p->flags( ifPRE_PROCESS ) && ( p != master_modal ) ) p->handle_event( ev );
- if( items_changed ) goto skip;
- p = p->nextl();
- }
- c = NULL;
- if( ( ev.code & ( evKEYBOARD|evCOMMAND ) ) && ( current ) )
- {
- current->handle_event( ev );
- c = current;
- }
- if( !items_changed )
- {
- p = first();
- while( ( p != NULL ) && ( ev.code != evNOTHING ) )
- {
- if( ( p != c ) && !p->flags( ifPRE_PROCESS ) ) p->handle_event( ev );
- if( items_changed ) break;
- p = p->nextl();
- }
- }
- }
- skip:
- if( isit_4u( ev ) )
- {
- event_handler( ev );
- if( ( ev.code == evCOMMAND ) && ( ev.destination == this ) )
- {
- switch( ev.CMD_CODE )
- {
- case cmDONE:
- if( valid( cmDONE ) && ( !state( isSELECTED ) || release_focus() ) )
- {
- if( state( isMODAL ) )
- {
- put_command( this, cmDONE );
- stop( cmDONE );
- }
- else
- DELETE( this );
- break;
- }
- ev.destination = NULL;
- return;
- case cmFOCUS:
- focus(); break;
- case cmSELECT:
- set_state( isSELECTED, 1 ); break;
- case cmENABLE:
- set_state( isDISABLED, 0 ); break;
- case cmDISABLE:
- set_state( isDISABLED, 1 ); break;
- case cmHIDE:
- set_state( isHIDDEN, 1 ); break;
- case cmSHOW:
- set_state( isHIDDEN, 0 ); break;
- default:
- return;
- }
- handled( ev );
- }
- }
- }
-
- /*
- Description:
- Construct a command message and call handle_event.
- Use 'command_info' prefix to specify command info ptr and size.
- Note:
- If info isn't NULL, and size isn't 0, then command info is disposed.
- Entry:
- receiver: pointer to the receiver, or NULL;
- cmd_code: command code.
- Exit:
- evNOTHING if command has been serviced.
- */
- Titem *Titem::handle_command( Titem *receiver, uint cmd_code )
- {
- Tevent ev;
-
- ev.code = evCOMMAND;
- ev.priority = 0;
- ev.destination = receiver;
- ev.CMD_CODE = cmd_code;
- ev.CMD_INFO = command_information;
- ev.CMD_SIZE = command_size;
- command_size = 0;
- command_information = NULL;
- handle_event( ev );
- return (Titem *) ev.destination;
- }
-
- /*
- Description:
- Determine if the exec loop can be terminated via stop_code. Can be
- overriden to handle special cases.
- Entry:
- stop_code.
- Exit:
- 1 if item allows current modal loop to be terminated by stop_code,
- 0 otherwise.
- */
- boolean Titem::valid( uint command )
- {
- Titem *p;
-
- if( !state( isVALID ) ) return 0;
- p = first();
- while( p != NULL )
- {
- if( !p->valid( command ) ) return 0;
- p = p->nextl();
- }
- return 1;
- }
-
- /*
- Description:
- Main modal loop method. Collect and pass events to the handle_event()
- until a call to stop() occurred.
- Exit:
- Return stop code passed to stop().
- */
- uint Titem::exec( void )
- {
- Titem *save_modal, *save_current;
- Tevent ev;
-
- optimize_bounds();
- save_modal = modal_item;
- if( save_modal != NULL ) save_modal->set_state( isMODAL+isFOCUSED, 0 );
- modal_item = this;
- set_state( isMODAL+isFOCUSED, 1 );
- if( owner != NULL )
- {
- save_current = owner->current;
- owner->current = this;
- }
- if( current != NULL ) current->focus();
- for( stop_state=0; stop_state==0; )
- {
- get_event( ev );
- handle_event( ev );
- }
- if( owner != NULL ) owner->current = save_current;
- set_state( isMODAL+isFOCUSED, 0 );
- modal_item = save_modal;
- if( modal_item != NULL ) modal_item->set_state( isMODAL+isFOCUSED, 1 );
- return stop_state;
- }
-
- /*
- Description:
- Include item, execute it, then exclude it.
- Entry:
- p: pointer to the item to be executed;
- _x, _y: coordinates for the item.
- Exit:
- Exec stop code.
- */
- uint Titem::exec_item( Titem *p, int _x, int _y )
- {
- uint result;
-
- if( p != NULL )
- {
- put_in( p, _x, _y );
- result = p->exec();
- remove( p );
- return result;
- }
- else
- return cmCANCEL;
- }
-
- /*
- Description:
- Includes item in the list of subitems.
- Entry:
- v: pointer to the item to be included;
- _x, _y: item coordinates.
- */
- void Titem::put_in( Titem *v, int _x, int _y )
- {
- v->x = _x; v->y = _y;
- if( v->x == xCENTER ) v->x = ( xl - v->xl ) >> 1;
- if( v->y == yCENTER ) v->y = ( yl - v->yl ) >> 1;
- if( v->xl == xlMAX ) v->resize( xl, v->yl );
- if( v->yl == ylMAX ) v->resize( v->xl, yl );
- v->owner = this;
- if( last == NULL )
- v->next = v, last = v;
- else
- v->next = last->next, last->next = v;
- v->set_state( state_word & ( isACTIVE+isALIVE+isACCESSABLE+isDISABLED ), 1 );
- v->initialize();
- v->calc_bounds( 0, 0 );
- v->redraw();
- #ifndef NOHELP
- v->get_help_ctx();
- #endif
- application->or_events_mask( v );
- if( v->flags( ifSELECTABLE ) && !v->state( isHIDDEN ) )
- v->set_state( isSELECTED, 1 );
- items_changed = 1;
- pop_top_items();
- update_bounds( v );
- }
-
- /*
- Description:
- Exclude a subitem from the subitems list.
- Entry:
- v: pointer to the item to be excluded.
- Exit:
- 0 if item !found in the subitems list,
- 1 otherwise.
- */
- boolean Titem::remove( Titem *v )
- {
- boolean f;
- Titem *l;
- Titem *p;
-
- p = last;
- do
- {
- l = p;
- p = p->next;
- if( p == v )
- {
- if( ( f = ( current == v ) ) != 0 )
- {
- v->set_state( isSELECTED, 0 );
- if( v->state( isSELECTED ) ) break;
- }
- v->redraw();
- if( p == l )
- last = NULL;
- else
- {
- l->next = p->next;
- if( p == last ) last = l;
- }
- if( f )
- {
- f = !v->state( isON_TOP );
- do
- {
- f = !f;
- for( p=first(); p!=NULL; p=p->nextl() )
- if( p->flags(ifSELECTABLE) && p->state(isALIVE) && (f || !p->state(isON_TOP)) )
- {
- p->set_state( isSELECTED, 1 );
- f = 1;
- break;
- }
- }
- while( !f );
- }
- v->next = NULL;
- v->owner = NULL;
- application->update_events_mask();
- items_changed = 1;
- req_update( this );
- return 1;
- }
- }
- while( p != last );
- return 0;
- }
-
- /*
- Description:
- Update bounds as subitem was moved/resized. This do not obtain min bounds
- for the item, it can only enlarge bounding rectangle. Min bounds are
- calculated at idle time calling optimize_bounds.
- Entry:
- p - subitem that has been moved/resized.
- Note:
- p must be valid subitem pointer.
- */
- void Titem::update_bounds( Titem *p )
- {
- int sx, sy, bx, by, xx, yy;
-
- if( p->flags( ifVISIBLE ) && !p->state( isHIDDEN ) )
- {
- make_global( bound_x, bound_y, sx, sy );
- p->make_global( p->bound_x, p->bound_y, bx, by );
- xx = sx - bx;
- yy = sy - by;
- if( xx > 0 )
- {
- bound_xl += xx;
- sx = bx;
- }
- if( yy > 0 )
- {
- bound_yl += yy;
- sy = by;
- }
- xx = ( bx + p->bound_xl ) - ( sx + bound_xl );
- yy = ( by + p->bound_yl ) - ( sy + bound_yl );
- if( xx > 0 ) bound_xl += xx;
- if( yy > 0 ) bound_yl += yy;
- make_local( sx, sy, bound_x, bound_y );
- req_update( this );
- if( owner != NULL ) owner->update_bounds( this );
- }
- }
-
- /*
- Description:
- Optimize bounding rectangle by calling update_bounds for each subitem.
- */
- void Titem::optimize_bounds( void )
- {
- int sx, sy, bx, by, xx, yy;
- Titem *p;
-
- bound_xl = xl; bound_yl = yl;
- if( state( isICONIZED ) )
- {
- bound_x = 0;
- bound_y = 0;
- }
- else
- {
- get_origin( sx, sy );
- p = first();
- while( p != NULL )
- {
- if( p->flags( ifVISIBLE ) && !p->state( isHIDDEN ) )
- {
- p->optimize_bounds();
- p->make_global( p->bound_x, p->bound_y, bx, by );
- xx = sx - bx;
- yy = sy - by;
- if( xx > 0 )
- {
- bound_xl += xx;
- sx = bx;
- }
- if( yy > 0 )
- {
- bound_yl += yy;
- sy = by;
- }
- xx = ( bx + p->bound_xl ) - ( sx + bound_xl );
- yy = ( by + p->bound_yl ) - ( sy + bound_yl );
- if( xx > 0 ) bound_xl += xx;
- if( yy > 0 ) bound_yl += yy;
- }
- p = p->nextl();
- }
- make_local( sx, sy, bound_x, bound_y );
- }
- }
-
- /*
- Description:
- Move specified item to the front of the subitems list, but after the
- 'always on top' items.
- Entry:
- w: pointer to the item to be moved to front.
- */
- void Titem::pop_item( Titem *w )
- {
- Titem *p, *l;
-
- if( ( last == NULL ) || ( last->next == w ) ) return;
- p = last;
- do
- {
- l = p;
- p = p->next;
- if( p == w )
- {
- p->redraw();
- if( p == last )
- last = l;
- else
- {
- l->next = p->next;
- p->next = last->next;
- last->next = p;
- }
- items_changed = 1;
- pop_top_items();
- break;
- }
- }
- while( p != last );
- }
-
- //Titem protected:
-
- /*
- Description:
- Called when item gets focused.
- */
- void Titem::get_focused( void )
- {
- }
-
- /*
- Description:
- Called when item loose focus. Return 0 if the item want to keep
- the focus.
- */
- boolean Titem::release_focus( void )
- {
- if( current != NULL ) return current->release_focus();
- return 1;
- }
-
- /*
- Description:
- Called when item has been just inserted in another item, and whenever
- its owner has been resized. Can be overriden to drag item when owner
- resizes, etc.
- */
- void Titem::calc_bounds( int delta_xl, int delta_yl )
- {
- int _x, _y, _xl, _yl, old_xl, old_yl;
-
- old_xl = owner->xl - delta_xl; old_yl = owner->yl - delta_yl;
- if( ( !old_xl ) || ( !old_yl ) ) return;
- _x = x; _y = y; _xl = xl; _yl = yl;
- if( drag_mode & dmDRAG_HOR )
- if( drag_mode & dmDRAG_REL )
- _x = ( x * xl ) / old_xl;
- else
- _x = x + delta_xl;
- if( drag_mode & dmDRAG_VER )
- if( drag_mode & dmDRAG_REL )
- _y = ( y * yl ) / old_yl;
- else
- _y = y + delta_yl;
- if( grow_mode & gmGROW_HOR )
- if( grow_mode & gmGROW_REL )
- _xl = ( xl * xl ) / old_xl;
- else
- _xl = xl + delta_xl;
- if( grow_mode & gmGROW_VER )
- if( grow_mode & gmGROW_REL )
- _yl = ( yl * yl ) / old_yl;
- else
- _yl = yl + delta_yl;
- if( ( _x != x ) || ( _y != y ) ) drag( _x, _y );
- if( ( _xl != xl ) || ( _yl != yl ) ) resize( _xl, _yl );
- }
-
- /*
- Description:
- A heavy item draw can call get_clip_rect to obtain actual bounds of the
- rectangle that need to be redrawn.
- Note:
- Returned coordinates are converted to local.
- */
- void Titem::get_clip_rect( int &_x, int &_y, int &_xl, int &_yl )
- {
- _x = current_dc->x + current_dc->region_x;
- _y = current_dc->y + current_dc->region_y;
- _xl = current_dc->region_xl;
- _yl = current_dc->region_yl;
- make_local( _x, _y, _x, _y );
- if( _x < 0 ) _xl += _x, _x = 0;
- if( _y < 0 ) _yl += _y, _y = 0;
- if( _xl > xl ) _xl = xl;
- if( _yl > yl ) _yl = yl;
- }
-
- /*
- Description:
- Determine if the item is in colision with the screen DC region. Use
- to determine if the item is visible on the screen. See PVDC.CPP for
- details.
- Exit:
- 0 - neither item or it's subitems are exposed
- 1 - item or it's subitems are exposed
- 2 - item is exposed
- */
- int Titem::exposed( void )
- {
- int a, b, rx, ry;
- uint rxl, ryl;
- int result;
-
- get_origin( a, b );
- rx = screen_dc->region_x; ry = screen_dc->region_y;
- rxl = screen_dc->region_xl; ryl = screen_dc->region_yl;
- result = 0;
- if( rect_colision( a + bound_x, b + bound_y, bound_xl, bound_yl,
- rx, ry, rxl, ryl ) ) result = 1;
- if( rect_colision( a, b, xl, yl, rx, ry, rxl, ryl ) ) result = 2;
- current_dc->set_region( rx - current_dc->x, ry - current_dc->y, rxl, ryl );
- return result;
- }
-
- /*
- Description:
- Call all the subitems paint to update item itself.
- */
- void Titem::reverse_paint( Titem *p )
- {
- int a, b;
-
- p = p->next;
- if( p != last )
- {
- p->get_origin( a, b );
- if( ( a > current_dc->x ) ||
- ( b > current_dc->y ) ||
- ( a + p->xl < current_dc->x + current_dc->xl ) ||
- ( b + p->yl < current_dc->y + current_dc->yl ) ||
- !p->state( isALIVE ) ) reverse_paint( p );
- }
- p->paint();
- }
-
- void Titem::paint( void )
- {
- int is_exposed;
-
- if( state( isALIVE ) && ( is_exposed = exposed() ) )
- {
- int a, b;
-
- if( is_exposed == 2 )
- {
- get_origin( a, b );
- current_dc->set_base( a - current_dc->x, b - current_dc->y );
- set_palette();
- draw();
- }
- if( !state( isICONIZED ) && last != NULL ) reverse_paint( last );
- }
- }
-
- /*
- Description:
- Set up palette. Called just before a call to draw. By default calls
- owner's set palette.
- */
- void Titem::set_palette( void )
- {
- text_attr = backgrnd_attr;
- if( text_attr ) return;
- if( owner != NULL ) owner->set_palette();
- }
-
- /*
- Description:
- Draw the item. Must cover all the item rectangle.
- On entry:
- DC base is set to item's upper-left corner, palette is initialized.
- */
- void Titem::draw( void )
- {
- static char *t = "|r. |l.";
-
- if( ( last == NULL ) || !text_attr ) return;
- t[2] = (char) xl; t[3] = backgrnd_char; t[6] = (char) yl;
- txt( t );
- }
-
- /*
- Description:
- Called when item has been just inserted in another item.
- */
- void Titem::initialize( void )
- {
- }
-
- /*
- Description:
- Returns 1 if event can be serviced by the item at the moment. Also
- used to set up local message fields.
- Entry:
- ev: event.
- */
- boolean Titem::isit_4u( Tevent &ev )
- {
- if( ( ( ev.code < evCOMMAND ) && state( isDISABLED ) ) ||
- ( !( event_mask & ev.code ) ||
- ( ( ev.destination != NULL ) && ( ev.destination != this ) ) ) )
- return 0;
- else
- {
- #ifndef NOMOUSE
- if( (ev.code&evMOUSE)
- #ifdef HGR
- || (ev.code&evHGR_MOUSE)
- #endif
- )
- if( state( isALIVE ) )
- {
- make_local( ev.GLOBAL_X, ev.GLOBAL_Y, ev.LOCAL_X, ev.LOCAL_Y );
- #ifdef HGR
- int a, b; get_origin( a, b );
- ev.LOCAL_HGR_X=ev.GLOBAL_HGR_X-a*8;
- ev.LOCAL_HGR_Y=ev.GLOBAL_HGR_Y-b*16;
- #endif
- ev.INSIDE = check_inside( ev.GLOBAL_X, ev.GLOBAL_Y );
- return 1;
- }
- else
- return 0;
- #endif
- }
- return 1;
- }
-
- /*
- Description:
- Service the passed message. If you override this method you shoud call
- inherited event_handler if you have !serviced the message.
- Entry:
- ev: event.
- Exit:
- ev.code = evNOTHING if event accepted and serviced.
- */
- void Titem::event_handler( Tevent &ev )
- {
- #ifndef NOHELP
- if( state( isFOCUSED|isMODAL ) &&
- ( ( ( ev.code == evCOMMAND ) && ( ev.CMD_CODE == cmHELP ) ) ||
- ( ( ev.code == evKEY_PRESS ) && ( ev.ASCII == kF1 ) ) ) )
- {
- if( state( isALIVE ) )
- online_help( help_ctx );
- else
- online_help( 0 );
- handled( ev );
- }
- #endif
- #ifndef NOMOUSE
- if( ( ev.code == evMOUSE_DOWN ) && ev.INSIDE )
- {
- pop_up();
- if( flags( ifSELECTABLE ) && !state( isFOCUSED ) ) focus();
- }
- #endif
- }
-
- /*
- Description:
- Call owner's or 'hardware' get_event.
- Exit:
- ev: event;
- */
- void Titem::get_event( Tevent &ev )
- {
- if( owner != NULL )
- owner->get_event( ev );
- else
- ::get_event( ev );
- }
-
- /*
- Description:
- Get (wait for) a mouse event. Returns 0 if event is evMOUSE_UP.
- Use for dragging items w/ the mouse.
- Exit:
- ev: event.
- */
- #ifndef NOMOUSE
- boolean Titem::get_mouse( Tevent &ev, uint mask )
- {
- mask |= evMOUSE_UP;
- do
- {
- get_event( ev );
- }
- while( !isit_4u( ev ) || !( ev.code & mask ) );
- return ev.code != evMOUSE_UP;
- }
- #endif
-
- /*
- Description:
- Get (wait for) a keyboard event.
- Exit:
- ev: event.
- */
- void Titem::get_key( Tevent &ev, uint mask )
- {
- do
- {
- get_event( ev );
- }
- while( !isit_4u( ev ) || !( ev.code & mask ) );
- }
-
- /*
- Description:
- Call owner's or 'hardware' put_event.
- Entry:
- ev: event to put.
- */
- void Titem::put_event( Tevent &ev )
- {
- if( owner != NULL )
- owner->put_event( ev );
- else
- ::put_event( ev );
- }
-
- /*
- Description:
- Construct a command message and call put_event.
- Entry:
- receiver: pointer to the receiver, or NULL.
- cmd_code: command code.
- */
- void Titem::put_command( Titem *receiver, uint cmd_code )
- {
- Tevent ev;
-
- ev.code = evCOMMAND;
- ev.priority = 0;
- ev.destination = receiver;
- ev.CMD_CODE = cmd_code;
- ev.CMD_INFO = command_information;
- ev.CMD_SIZE = command_size;
- put_event( ev );
- }
-
- /*
- Description:
- Called from an event_handler to indicate that event has been
- successfully handled.
- Entry:
- ev: handled event.
- */
- void Titem::handled( Tevent &ev )
- {
- ev.code = evNOTHING;
- ev.destination = this;
- }
-
- /*
- Description:
- Terminate exec loop by stop_code.
- Entry:
- stop_code.
- */
- void Titem::stop( uint stop_code )
- {
- if( state( isMODAL ) )
- {
- if( valid( stop_code ) ) stop_state = stop_code;
- }
- else
- owner->stop( stop_code );
- }
-
- /*
- Description:
- Called when user accept a dialog box, allowing item to update its
- information.
- */
- void Titem::ok_item( void )
- {
- Titem *p;
-
- p = first();
- while( p != NULL )
- {
- p->ok_item();
- p = p->nextl();
- }
- }
-
- /*
- Description:
- Called when user cancel a dialog box, allowing item to undo changes.
- */
- void Titem::cancel_item( void )
- {
- Titem *p;
-
- p = first();
- while( p != NULL )
- {
- p->cancel_item();
- p = p->nextl();
- }
- }
-
- /*
- Description:
- Called whenever subitems list has been changed and shoud pop the
- 'always on top' items to the top.
- */
- void Titem::pop_top_items( void )
- {
- if( items_changed && ( last != NULL ) ) do_pop_top_items( last );
- }
-
- boolean Titem::cenabled( uint cmd )
- {
- if( owner != NULL ) return owner->cenabled( cmd );
- return ::cenabled( cmd );
- }
-
- boolean Titem::cdisabled( uint cmd )
- {
- if( owner != NULL ) return owner->cdisabled( cmd );
- return ::cdisabled( cmd );
- }
-
- void Titem::cenable( uint cmd )
- {
- if( owner != NULL )
- owner->cenable( cmd );
- else
- ::cenable( cmd );
- }
-
- void Titem::cdisable( uint cmd )
- {
- if( owner != NULL )
- owner->cdisable( cmd );
- else
- ::cdisable( cmd );
- }
-
- void Titem::cstate( uint cmd, boolean enable )
- {
- if( owner != NULL )
- owner->cstate( cmd, enable );
- else
- ::cstate( cmd, enable );
- }
-
- /*
- Description:
- Called when user drop an object over the item. Used for drag&drop.
- Entry:
- data: pointer dropped data.
- */
- void Titem::drop( void *data )
- {
- Titem *p;
-
- p = first();
- while( p != NULL )
- {
- if( p->drop_id == drop_id ) p->drop( data );
- p = p->nextl();
- }
- }
-
-
- //Titem private:
-
- /*
- Description:
- Return the help context of the item. If item has no help context
- return the owner's help context, and so on.
- */
- #ifndef NOHELP
- uint Titem::get_help_ctx( void )
- {
- Titem *p;
- uint ht;
-
- ht = help_ctx;
- p = owner;
- while( !ht && ( p != NULL ) )
- {
- ht = p->help_ctx;
- p = p->owner;
- }
- help_ctx = ht;
- p = first();
- while( p != NULL )
- {
- p->get_help_ctx();
- p = p->nextl();
- }
- return ht;
- }
- #endif
-
-
- void Titem::do_pop_top_items( Titem *p )
- {
- static Titem *l, *i;
-
- p = p->next;
- if( p != last ) do_pop_top_items( p );
- if( p->state( isON_TOP ) )
- {
- i = last;
- do
- {
- l = i;
- i = i->next;
- }
- while( i != p );
- if( p == last )
- last = l;
- else
- {
- l->next = p->next;
- p->next = last->next;
- last->next = p;
- }
- }
- }
-
-
- #ifndef NOMOUSE
-
- //Tdrag_drop
-
- class Tdrag_drop: public Titem
- {
- public:
- long id;
- void *data;
- Tdraw_proc draw_proc;
- boolean can_drop;
- Tdrag_drop( int _xl, int _yl, long _id, void *_data, Tdraw_proc _draw_proc );
-
- protected:
- virtual void set_palette( void );
- virtual void draw( void );
- virtual boolean isit_4u( Tevent &ev );
- virtual void event_handler( Tevent &ev );
- Titem *get_drop_item( Titem *p, int _x, int _y );
- };
-
- static int current_xl = 0;
- static int current_yl = 0;
- static Tdraw_proc current_draw_proc = NULL;
-
- void _drag_draw( int xl, int yl, Tdraw_proc draw_proc )
- {
- current_xl = xl;
- current_yl = yl;
- current_draw_proc = draw_proc;
- }
-
- void pick_up( int x, int y, long id, void *data )
- {
- int xl, yl;
- Tdrag_drop *drag_drop;
-
- xl = 2; yl = 1;
- if( current_xl )
- {
- xl = current_xl;
- yl = current_yl;
- }
- drag_drop = NEW( Tdrag_drop( xl, yl, id, data, current_draw_proc ) );
- current_xl = 0; current_draw_proc = NULL;
- application->make_local( x, y, x, y );
- application->put_in( drag_drop, x, y );
- }
-
- //Tdrag_drop publics:
-
- Tdrag_drop::Tdrag_drop( int _xl, int _yl, long _id, void *_data, Tdraw_proc _draw_proc ):
- Titem( _xl, _yl )
- {
- set_flags( ifRESIZEABLE+ifSELECTABLE, 0 );
- set_state( isON_TOP+isHIDDEN, 1 );
- id = _id;
- data = _data;
- draw_proc = _draw_proc;
- can_drop = 0;
- }
-
- //Tdrag_drop protected:
-
- void Tdrag_drop::set_palette( void )
- {
- if( can_drop )
- text_attr = pal_drag_drop.normal;
- else
- text_attr = pal_drag_drop.disabled;
- }
-
- void Tdrag_drop::draw( void )
- {
- if( draw_proc != NULL )
- draw_proc();
- else
- direct_txt( " " );
- }
-
- boolean Tdrag_drop::isit_4u( Tevent &ev )
- {
- if( ev.code & evMOUSE )
- {
- make_local( ev.GLOBAL_X, ev.GLOBAL_Y, ev.LOCAL_X, ev.LOCAL_Y );
- ev.INSIDE = check_inside( ev.GLOBAL_X, ev.GLOBAL_Y );
- return 1;
- }
- return Titem::isit_4u( ev );
- }
-
- void Tdrag_drop::event_handler( Tevent &ev )
- {
- int xx, yy;
- Titem *p;
-
- Titem::event_handler( ev );
- switch( ev.code )
- {
- case evMOUSE_DRAG:
- set_state( isHIDDEN, 0 );
- owner->make_local( ev.GLOBAL_X, ev.GLOBAL_Y, xx, yy );
- drag( xx, yy );
- p = get_drop_item( application, ev.GLOBAL_X, ev.GLOBAL_Y );
- can_drop = p->drop_id == id;
- handled( ev );
- break;
- case evMOUSE_UP:
- if( can_drop && !state( isHIDDEN ) )
- get_drop_item( application, ev.GLOBAL_X, ev.GLOBAL_Y )->drop( data );
- put_command( this, cmDONE );
- handled( ev );
- }
- }
-
- Titem *Tdrag_drop::get_drop_item( Titem *p, int _x, int _y )
- {
- Titem *i;
-
- i = p->first();
- while( i != NULL )
- {
- if( i->state( isALIVE ) &&
- i->check_inside( _x, _y ) &&
- ( i != this ) )
- return get_drop_item( i, _x, _y );
- i = i->nextl();
- }
- return p;
- }
-
- #endif
-