Конференция "Основная" » Как дисэйблить кнопки если операция не поддерживается… ?
 
  • Kolan © (25.01.08 15:32) [0]
    Здравствуйте,
     Допустим у нас есть два вида объектов А и Б.

    С ними можно выполнять похожие по смыслы(интерфейсу) операции, только реализованы они будут по разному.

    Понятно, что удобно узать стратегии. Тогда надо определить общий интерфейс, и сделать его конкретный реализации для А и Б.

    Пример:
    IItemsOperationsController = interface
       ['{3574BBB8-1413-4508-AD48-F4BEFFC88A28}']
       procedure AddItem;
       procedure DeleteCurrentItem;
       procedure SetCurrentItem(AnObject: TObject);
       procedure PerformOpertionWithCurretnItem(ADeviceOperationPerformer:
         IDeviceOperationPerformer);
     end;

     TCustomItemsOperationsController = class(TInterfacedObject, IItemsOperationsController)
     public
       procedure AddItem; virtual; abstract;
       procedure DeleteCurrentItem; virtual; abstract;
       procedure SetCurrentItem(AnObject: TObject); virtual; abstract;
       procedure PerformOpertionWithCurretnItem(ADeviceOperationPerformer:
         IDeviceOperationPerformer); virtual; abstract;
     end;

     TNetItemsOperationsController = class(TCustomItemsOperationsController)
     protected
       function QueryNetName(var AName: string): Boolean;
     public
       procedure AddItem; override;
       procedure DeleteCurrentItem; override;
       procedure SetCurrentItem(AnObject: TObject); override;
       procedure PerformOpertionWithCurretnItem(ADeviceOperationPerformer:
         IDeviceOperationPerformer); override;
     end;

     TDeviceItemsOperationsController = class(TCustomItemsOperationsController)
     protected
       function QueryDeviceAddress(var AnAddress: Byte): Boolean;
     public
       procedure AddItem; override;
       procedure DeleteCurrentItem; override;
       procedure SetCurrentItem(AnObject: TObject); override;
       procedure PerformOpertionWithCurretnItem(ADeviceOperationPerformer:
         IDeviceOperationPerformer); override;
     end;



    Тогда вызов будет такой(это код экшена):
     procedure TMainForm.DeleteItemExecute(Sender: TObject);
    begin
     GetConfigurationUtilityController.DeleteCurrentItem;
    end;



    Где
    GetConfigurationUtilityController

    — это синглетон, который делегирует вызов нужному контроллеру.
    procedure TConfigurationUtilityController.DeleteCurrentItem;
    begin
     GetItemsOperationsController.DeleteCurrentItem;
    end;



    Но вот проблемма, объекты типа Б не поддерживают операцию удаления(например). Для них хорошо бы кнопочку(экшен) удалить сделать недоступной.

    Вопрос: Как?
  • Palladin © (25.01.08 15:38) [1]
    определяем базовый интерфейс
    IItemsOperationsController = interface
      procedure AddItem;
      procedure DeleteCurrentItem;
      procedure SetCurrentItem(AnObject: TObject);
      procedure PerformOpertionWithCurretnItem(ADeviceOperationPerformer:
        IDeviceOperationPerformer);
    end;
    определяем интерфейс наследник с поддержкой удаления
    IItemsOperationsControllerWithDeleteSupport = interface(IItemsOperationsController)
      procedure DeleteCurrentItem;
    end;

    и фсе... теперь можно определять поддержку удаления поддержкой интерфейса
  • Palladin © (25.01.08 15:39) [2]
    ой, в базе обшибся, там Delete не нужен
  • Kolan © (25.01.08 15:47) [3]
    > и фсе… теперь можно определять поддержку удаления поддержкой
    > интерфейса

    Я примерно понял. Только ты, плз пример напиши…
    Нопонятно кто должен проверять поддержку и дисейблить…
  • clickmaker © (25.01.08 15:53) [4]
    IsSupported(operationName): boolean; virtual
    а вызывать в Action.OnUpdate
    так, что-ли?
  • Kolan © (25.01.08 15:57) [5]
    > IsSupported(operationName): boolean; virtual

    Ну у кого это операция будет реализована?

    В данном примере в Синглетоне (GetConfigurationUtilityController — это синглетон, который делегирует вызов нужному контроллеру.)?

    Что-то вроде:

    procedure TMainForm.DeleteItemUpdate(Sender: TObject);
    begin
     (Sender as TAction).Enabled := GetConfigurationUtilityController.GetItemsOperationsController.GetInterface(IIte msOperationsControllerWithDeleteSupport, Int);    
    end;



    ?
  • clickmaker © (25.01.08 16:05) [6]

    > [5] Kolan ©   (25.01.08 15:57)

    что-то у тебя мудренно как-то всё...
    наверно, в IItemsOperationsController и объявить
    а переопределять ниже по иерархии
  • Kolan © (25.01.08 16:16) [7]
    > а переопределять ниже по иерархии

    Непонял.

    Как в [5] по идее не надо будет ничего перопределять…

    ЗЫ
     Я же поэтому и прошу примерчик, а то непонятно…
  • clickmaker © (25.01.08 16:19) [8]

    > [7] Kolan ©   (25.01.08 16:16)

    ну я тогда не понял твою задумку...
    мне как-то старый добрый полиморфизм ближе в этом отношении
  • Palladin © (25.01.08 16:22) [9]

    > procedure TMainForm.DeleteItemUpdate(Sender: TObject);
    > begin
    >  (Sender as TAction).Enabled := GetConfigurationUtilityController.GetItemsOperationsController.GetInterface(IIte  
    > msOperationsControllerWithDeleteSupport, Int);    
    > end;

    да, именно так
  • offff (25.01.08 16:27) [10]

    > Но вот проблемма, объекты типа Б не поддерживают операцию
    > удаления(например). Для них хорошо бы кнопочку(экшен) удалить
    > сделать недоступной.


    Замечания к реализации. IMHO

    Тогда и интерфейс IItemsOperationsController не должен ее содержать.

    Добиться можно выделив операцию в отдельную сущность.
    А именно либо отдельный интерфейс, либо класс на каждую операцию.
    Аля command согласно GOF.
  • offff (25.01.08 16:27) [11]
    Удалено модератором
    Примечание: дубль
  • offff (25.01.08 16:34) [12]
    Либо сделать посетителя операций. и сделать посетителя Menu Manager.

    IItemsOperationsController = interface
    function OpsVisitor(...)  <- сюда твоего Menu Manager
      {

      }
     

    end
  • offff (25.01.08 16:34) [13]
    Удалено модератором
    Примечание: дубль
  • Kolan © (25.01.08 16:34) [14]
    > А именно либо отдельный интерфейс

    Паладин так и предлагает.


    > Аля command согласно GOF

    Возится с каждой командой долго выходит…
  • Kolan © (25.01.08 16:37) [15]
    > function OpsVisitor(…)  <— сюда твоего Menu Manager

    Ну и что я буду говорить этому менеджеру? Задисейбли кнопку «Удалить». А если кнопок много? Что же их все пересчислять?

    Паладин действительно прав. Получается я контракт нарущил. Говорю что оддерживаю удаление, а на самом деле нет… Осталось грамотно связать…
  • offff (25.01.08 16:42) [16]

    > Kolan ©   (25.01.08 16:37) [15]


    Menu Manager - отключает все кнопки.

    MenuManager=class(CommandVisitor)
    procedure OpAdd
    procedure OpRemove
    Procedure OpCurrent
    end;

    Реализатор IItemsOperationsController пробегает по всем его коммандам и делает вызов

    AbstractCommand.Accept(visitor:CommandVisitor)  

    procedure MenuManager.OpAdd
    begin
    ADDITEM.VISIBLE:=TRUE;
    end;

    procedure MenuManager.OpRemove
    begin
    RemoveITEM.VISIBLE:=TRUE;
    end;

    Procedure MenuManager.OpCurrent
    begin
    ....
    end;
  • offff (25.01.08 16:42) [17]
    Удалено модератором
    Примечание: да что'ж ты дублями то :)
  • oxffff © (25.01.08 16:47) [18]
    Что то задублилось у меня. Sorry.

    Что касаемо реализации то я уже тут предлагал улучшенную реализацию GOF паттерна VISITOR без привязки к VMT.
    Кстати напишу в своем блоге об этом.

    :)
  • oxffff © (25.01.08 16:49) [19]

    > offff   (25.01.08 16:42) [17]
    > Удалено модератором
    > Примечание: да что'ж ты дублями то :)


    Sorry снова. Сам не знаю что за дела. Под oxffff пользователем порядок.
    :)
 
Конференция "Основная" » Как дисэйблить кнопки если операция не поддерживается… ?
Есть новые Нет новых   [134482   +34][b:0][p:0.002]