Управление панелью инструментов: автоматный подход

//=========================================================
// Модуль, реализующий управление тулбарами
// Версия, выполненная с применением автоматного подхода

//======
// Обработчик события нажатия кнопки мыши на панели
//
int toolbar_btn_press( PtWidget_t *widget, ApInfo_t *apinfo,
                       PtCallbackInfo_t *cbinfo )
{
  toolbar_t         *tb = tb_data(widget) ;
                              // Указатель на данные панели
  PhEvent_t         *event = cbinfo->event ;
                              // Произошедшее событие
  PhPointerEvent_t  *edata = PhGetData( event ) ;
                     // Дополнительная информация о событии

  if( edata->buttons == Ph_BUTTON_MENU )
  {
    // Нажатая кнопка мыши - правая
    // Вызвать управляющий автомат
    A0( 10, tb, event ) ;
  } ;

  return( Pt_CONTINUE ) ;
} ;

//======
// Обработчик события отпускания кнопки мыши на панели
//
int toolbar_btn_release( PtWidget_t *widget,
                         ApInfo_t *apinfo,
                         PtCallbackInfo_t *cbinfo )
{
  toolbar_t         *tb = tb_data(widget) ;
                             // Указатель на данные тулбара
  PhEvent_t         *event = cbinfo->event ;
                             // Произошедшее событие
  PhPointerEvent_t  *edata = PhGetData( event ) ;
                     // Дополнительная информация о событии
  
  if(    event->subtype == Ph_EV_RELEASE_REAL
      && edata->buttons == Ph_BUTTON_MENU )
  {
    // Отпущенная кнопка мыши - правая
    // Вызвать управляющий автомат
    A0( 20, tb, event ) ;
  } ;

  return( Pt_CONTINUE ) ;
} ;

//======
// Обработчик события перемещения мыши с нажатой кнопкой
//
int toolbar_btn_move( PtWidget_t *widget, ApInfo_t *apinfo,
                      PtCallbackInfo_t *cbinfo )
{
  toolbar_t         *tb = tb_data(widget) ;
                              // Указатель на данные панели
  PhEvent_t         *event = cbinfo->event ;
                              // Произошедшее событие
  PhPointerEvent_t  *edata = PhGetData( event ) ;
                     // Дополнительная информация о событии

  if( edata->buttons == Ph_BUTTON_MENU )
  {
    // Правая кнопка нажата
    // Вызвать управляющий автомат
    A0( 30, tb, event ) ;
  } ;

  return( Pt_CONTINUE ) ;
} ;

//======
// Обработчик события пересечения курсором мыши
// границы панели
int toolbar_boundary( PtWidget_t *widget, ApInfo_t *apinfo,
                      PtCallbackInfo_t *cbinfo )
{
  toolbar_t  *tb = tb_data(widget) ;
                              // Указатель на данные панели
  PhEvent_t  *event = cbinfo->event ;
                              // Произошедшее событие
                                
  if( event->subtype == Ph_EV_PTR_LEAVE )
  {
    // Курсор мыши вышел за границу панели
    // Вызвать управляющий автомат
    A0( 40, tb, event ) ;
  } ;

  return( Pt_CONTINUE ) ;
} ;

//======
// Функция, реализующая автомат управления панелью
//
void A0( int e, toolbar_t *tb, PhEvent_t *event )
{
  int y_old = tb->y0 ;  
  
  #ifdef GRAPH_EVENTS_LOGGING
    log_exec( "A0", y_old, e ) ;
  #endif

  switch( tb->y0 )
  {
    case 0:
      if( e == 10 )                 tb->y0 = 1 ;
    break ;
    case 1:
      if( e == 20 ) { z30(tb) ;     tb->y0 = 0 ; }
      else
      if( e == 30 )                 tb->y0 = 2 ;
      else
      if( e == 40 )                 tb->y0 = 0 ;
    break ;
    case 2:
      if( e == 30 ) { z20(tb, event) ; }
      else
      if( e != 30 )                 tb->y0 = 0 ;
    break ;
    
    default:
      #ifdef GRAPH_ERRORS_LOGGING
        log_write( LOG_GRAPH_ERROR,
               "ОШИБКА В A0: неизвестное состояние!", 0 ) ;
      #endif
    break ;
  } ;
  
  // Если состояние не изменилось,
  // завершить выполнение функции
  if( y_old == tb->y0 ) goto A0_end ;

  #ifdef GRAPH_TRANS_LOGGING
    log_trans( "A0", y_old, tb->y0 ) ;
  #endif
  
  switch( tb->y0 )
  {
    case 1:
      z10(tb, event) ; z40(tb) ;
    break ;
    
    case 2:
      z20(tb, event) ;
    break;
  } ;
  
  A0_end: ;
  #ifdef GRAPH_ENDS_LOGGING
    log_end( "A0", tb->y0, e ) ;
  #endif
} ;

//======
// Запомнить координаты курсора мыши.
//
void z10( toolbar_t *tb, PhEvent_t *event )
{
  PhRect_t      *rect = NULL ;  // Координаты курсора мыши

  #ifdef ACTIONS_LOGGING
    log_write( LOG_ACTION,
           "z10. Запомнить координаты курсора мыши.", 0 ) ;
  #endif
  
  rect = PhGetRects( event ) ;    
  tb->drag_pos = rect->ul ;
} ;

//======
// Переместить панель
//
void z20( toolbar_t *tb, PhEvent_t *event )
{
  PhRect_t      *rect = NULL ;  // Координаты курсора мыши.
  
  #ifdef ACTIONS_LOGGING
    log_write( LOG_ACTION, "z20. Переместить панель.", 0);
  #endif
  
  rect = PhGetRects( event ) ;    
  toolbar_move( tb, rect->ul.x - tb->drag_pos.x,
                rect->ul.y - tb->drag_pos.y ) ;
} ;

//======
// Вызвать меню панели
//
void z30( toolbar_t *tb )
{
  #ifdef ACTIONS_LOGGING
    log_write( LOG_ACTION, "z30. Вызвать меню панели.", 0);
  #endif
  
  ApCreateModule( ABM_toolbar_menu, NULL, NULL ) ;
} ;

//======
// Поместить окно панели выше остальных.
//
void z40( toolbar_t *tb )
{
  #ifdef ACTIONS_LOGGING
    log_write( LOG_ACTION,
        "z40. Поместить окно панели поверх остальных.", 0);
  #endif
  
  PtWindowToFront( tb->wgt ) ;
} ;