Point Widget_pointerPos( Handle self, Bool set, Point p) { if ( !set) { p = apc_pointer_get_pos( self); apc_widget_map_points( self, false, 1, &p); return p; } apc_widget_map_points( self, true, 1, &p); apc_pointer_set_pos( self, p. x, p. y); return p; }
static void hshow( Handle self) { PWidget_vmt hintUnder = CWidget( var-> hintUnder); SV * text = hintUnder-> get_hint( var-> hintUnder); Point size = hintUnder-> get_size( var-> hintUnder); Point s = my-> get_size( self); Point fin = {0,0}; Point pos = fin; Point mouse = my-> get_pointerPos( self); Point hintSize; PWidget_vmt hintWidget = CWidget( var-> hintWidget); apc_widget_map_points( var-> hintUnder, true, 1, &pos); hintWidget-> set_text( var-> hintWidget, text); sv_free( text); hintSize = hintWidget-> get_size( var-> hintWidget); fin. x = mouse. x - 16; fin. y = pos. y - hintSize. y - 1; if ( fin. y > mouse. y - hintSize. y - 32) fin. y = mouse. y - hintSize. y - 32; if ( fin. x + hintSize. x >= s. x) fin. x = pos. x - hintSize. x; if ( fin. x < 0) fin. x = 0; if ( fin. y + hintSize. y >= s. y) fin. y = pos. y - hintSize. y; if ( fin. y < 0) fin. y = pos. y + size. y + 1; if ( fin. y < 0) fin. y = 0; hintWidget-> set_origin( var-> hintWidget, fin); hintWidget-> show( var-> hintWidget); hintWidget-> bring_to_front( var-> hintWidget); }
Handle Widget_next_positional( Handle self, int dx, int dy) { Handle horizon = self; int i, maxDiff = INT_MAX; Handle max = nilHandle; List candidates; Point p[2]; int minor[2], major[2], axis, extraDiff, ir[4]; /* In order to compute positional difference, using four penalties. To simplify algorithm, Rect will be translated to int[4] and minor, major and extraDiff assigned to array indices for those steps - minor for first and third, major for second and extraDiff for last one. */ axis = ( dx == 0) ? dy : dx; minor[0] = ( dx == 0) ? 0 : 1; minor[1] = minor[0] + 2; extraDiff = major[(axis < 0) ? 0 : 1] = ( dx == 0) ? 1 : 0; major[(axis < 0) ? 1 : 0] = extraDiff + 2; extraDiff = ( dx == 0) ? (( axis < 0) ? 0 : 2) : (( axis < 0) ? 1 : 3); while ( PWidget( horizon)-> owner) { if ( ( PWidget( horizon)-> options. optSystemSelectable) || /* fast check for CWindow */ ( PWidget( horizon)-> options. optModalHorizon) ) break; horizon = PWidget( horizon)-> owner; } if ( !CWidget( horizon)-> get_visible( horizon) || !CWidget( horizon)-> get_enabled( horizon)) return nilHandle; list_create( &candidates, 64, 64); fill_tab_candidates( &candidates, horizon); p[0].x = p[0].y = 0; p[1] = CWidget( self)-> get_size( self); apc_widget_map_points( self, true, 2, p); apc_widget_map_points( horizon, false, 2, p); ir[0] = p[0].x; ir[1] = p[0].y; ir[2] = p[1].x; ir[3] = p[1].y; for ( i = 0; i < candidates. count; i++) { int diff, ix[4]; Handle x = candidates. items[i]; if ( x == self) continue; p[0].x = p[0].y = 0; p[1] = CWidget( x)-> get_size( x); apc_widget_map_points( x, true, 2, p); apc_widget_map_points( horizon, false, 2, p); ix[0] = p[0].x; ix[1] = p[0].y; ix[2] = p[1].x; ix[3] = p[1].y; /* First step - checking if the widget is subject to comparison. It is not, if it's minor axis is not contiguous with self's */ if ( ix[ minor[0]] > ir[ minor[1]] || ix[ minor[1]] < ir[ minor[0]]) continue; /* Using x100 penalty for distance in major axis - and discarding those that of different sign */ diff = ( ix[ major[ 1]] - ir[ major[0]]) * 100 * axis; if ( diff < 0) continue; /* Adding x10 penalty for incomplete minor axis congruence. Addition goes in tenths, in a way to not allow congruence overweight major axis distance */ if ( ix[ minor[0]] > ir[ minor[0]]) diff += ( ix[ minor[0]] - ir[ minor[0]]) * 100 / ( ir[ minor[1]] - ir[ minor[0]]); if ( ix[ minor[1]] < ir[ minor[1]]) diff += ( ir[ minor[1]] - ix[ minor[1]]) * 100 / ( ir[ minor[1]] - ir[ minor[0]]); /* Adding 'distance from level' x1 penalty */ if (( ix[ extraDiff] - ir[ extraDiff]) * axis < 0) diff += abs( ix[ extraDiff] - ir[ extraDiff]); if ( diff < maxDiff) { max = x; maxDiff = diff; } } list_destroy( &candidates); return max; }