Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
berryCommandContributionItem.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 BlueBerry Platform
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 
19 #include "berryIMenuService.h"
20 #include "berryICommandService.h"
23 #include "berryIElementReference.h"
24 #include "berryIElementUpdater.h"
25 #include "berryUIElement.h"
26 
27 #include <berryICommandListener.h>
29 #include <berryIHandler.h>
30 #include <berryCommand.h>
31 #include <berryCommandEvent.h>
33 #include <berryCommandExceptions.h>
35 
36 #include "../berryDisplay.h"
37 #include "../berryAsyncRunnable.h"
38 
39 #include "../handlers/berryIHandlerService.h"
40 #include "../services/berryIServiceLocator.h"
41 
42 #include "../internal/berryWorkbenchPlugin.h"
43 
44 #include <QMenu>
45 #include <QMenuBar>
46 #include <QToolBar>
47 #include <QApplication>
48 
49 #include <QMetaMethod>
50 
51 namespace berry
52 {
53 
54 ContributionItem::Modes CommandContributionItem::modes = ContributionItem::MODE_FORCE_TEXT;
55 
56 
57 //class CommandUIElementListener : public IUIElementListener
58 //{
59 //private:
60 // CommandContributionItem* item;
61 
62 // public:
63 
64 // CommandUIElementListener(CommandContributionItem* item);
65 
66 // void UIElementDisposed(UIElement* item);
67 
68 //void UIElementSelected(SmartPointer<UIElement> item);
69 //};
70 
71 
73  const SmartPointer<CommandContributionItemParameter>& contributionParameters)
74  : ContributionItem(contributionParameters->id)
75  , action(nullptr)
76  , checkedState(false)
77 {
78  this->icon = contributionParameters->icon;
79  this->label = contributionParameters->label;
80  this->mnemonic = contributionParameters->mnemonic;
81  this->shortcut = contributionParameters->shortcut;
82  this->tooltip = contributionParameters->tooltip;
83  this->style = contributionParameters->style;
84  this->helpContextId = contributionParameters->helpContextId;
85  this->visibleEnabled = contributionParameters->visibleEnabled;
86  this->mode = contributionParameters->mode;
87 
88  menuService = contributionParameters->serviceLocator->GetService<IMenuService>();
89  commandService = contributionParameters->serviceLocator->GetService<ICommandService>();
90  handlerService = contributionParameters->serviceLocator->GetService<IHandlerService>();
91  // bindingService = (IBindingService) contributionParameters.serviceLocator
92  // .getService(IBindingService.class);
93 
94  this->CreateCommand(contributionParameters->commandId,
95  contributionParameters->parameters);
96 
97  if (command)
98  {
99  try
100  {
101  class CommandUIElement : public UIElement
102  {
103 
104  private:
106 
107  public:
108 
109  CommandUIElement(CommandContributionItem* item, IServiceLocator* serviceLocator)
110  : UIElement(serviceLocator), item(item) {}
111 
112  void SetText(const QString& text) override
113  {
114  item->SetText(text);
115  }
116 
117  void SetToolTip(const QString& text) override
118  {
119  item->SetToolTip(text);
120  }
121 
122  void SetIcon(const QIcon& icon) override
123  {
124  item->SetIcon(icon);
125  }
126 
127  void SetChecked(bool checked) override
128  {
129  item->SetChecked(checked);
130  }
131 
132  void SetDropDownId(const QString& id) override
133  {
134  item->dropDownMenuOverride = id;
135  }
136 
137  };
138 
139  UIElement::Pointer callback(new CommandUIElement(this,
140  contributionParameters->serviceLocator));
141 
142  elementRef = commandService->RegisterElementForCommand(command, callback);
143  command->GetCommand()->AddCommandListener(this->GetCommandListener());
144  this->SetImages(contributionParameters->serviceLocator,
145  contributionParameters->iconStyle);
146 
147  if (contributionParameters->helpContextId.isEmpty())
148  {
149  try
150  {
151  this->helpContextId = commandService->GetHelpContextId(
152  contributionParameters->commandId);
153  }
154  catch (const NotDefinedException& /*e*/)
155  {
156  // it's OK to not have a helpContextId
157  }
158  }
159  // IWorkbenchLocationService::Pointer wls = contributionParameters.serviceLocator
160  // ->GetService(IWorkbenchLocationService::GetManifestName()).Cast<IWorkbenchLocationService>();
161  // const IWorkbench* workbench = wls->GetWorkbench();;
162  // if (workbench != 0 && !helpContextId.empty()) {
163  // this->workbenchHelpSystem = workbench->GetHelpSystem();
164  // }
165  }
166  catch (const NotDefinedException& /*e*/)
167  {
168  WorkbenchPlugin::Log(QString("Unable to register menu item \"") + this->GetId()
169  + "\", command \"" + contributionParameters->commandId
170  + "\" not defined");
171  }
172  }
173 }
174 
175 void CommandContributionItem::Fill(QMenu* parent, QAction* before)
176 {
177  if (!command || action || parent == nullptr)
178  {
179  return;
180  }
181 
182  // Menus don't support the pulldown style
183  Style tmpStyle = style;
184  if (tmpStyle == STYLE_PULLDOWN)
185  tmpStyle = STYLE_PUSH;
186 
187  QAction* item = nullptr;
188  if (before)
189  {
190  item = new QAction(icon, label, parent);
191  parent->insertAction(before, item);
192  }
193  else
194  {
195  item = parent->addAction(icon, label);
196  }
197 
198  // Remove this when key binding support is fully implemented
199  if (!shortcut.isEmpty())
200  {
201  item->setShortcut(shortcut);
202  }
203  item->setData(QVariant::fromValue(Object::Pointer(this)));
204  item->setProperty("contributionItem", QVariant::fromValue(Object::Pointer(this)));
205 
206  // if (workbenchHelpSystem != null)
207  // {
208  // workbenchHelpSystem.setHelp(item, helpContextId);
209  // }
210 
211  connect(item, SIGNAL(triggered()), SLOT(HandleWidgetSelection()));
212  connect(item, SIGNAL(destroyed()), SLOT(HandleActionDestroyed()));
213  action = item;
214 
215  this->Update();
216  this->UpdateIcons();
217 
218  //bindingService.addBindingManagerListener(bindingManagerListener);
219 }
220 
221 void CommandContributionItem::Fill(QToolBar *parent, QAction *before)
222 {
223  if (!command || action || parent == nullptr)
224  {
225  return;
226  }
227 
228  QAction* item = nullptr;
229  if (before)
230  {
231  item = parent->addAction(icon, label);
232  }
233  else
234  {
235  item = new QAction(icon, label, parent);
236  parent->insertAction(before, item);
237  }
238  item->setData(QVariant::fromValue(Object::Pointer(this)));
239  item->setProperty("contributionItem", QVariant::fromValue(Object::Pointer(this)));
240 
241  connect(item, SIGNAL(triggered()), SLOT(HandleWidgetSelection()));
242  connect(item, SIGNAL(destroyed()), SLOT(HandleActionDestroyed()));
243  action = item;
244 
245  this->Update();
246  this->UpdateIcons();
247 
248  //bindingService.addBindingManagerListener(bindingManagerListener);
249 }
250 
252 {
253  this->Update(QString::null);
254 }
255 
256 void CommandContributionItem::Update(const QString& /*id*/)
257 {
258  if (action)
259  {
260  QWidget* parent = action->parentWidget();
261  if(qobject_cast<QMenu*>(parent))
262  {
263  this->UpdateMenuItem();
264  }
265  else if (qobject_cast<QMenuBar*>(parent))
266  {
267  this->UpdateMenuItem();
268  }
269  else if (qobject_cast<QToolBar*>(parent))
270  {
271  this->UpdateToolItem();
272  }
273  }
274 
275 }
276 
277 void CommandContributionItem::UpdateMenuItem()
278 {
279  QString text = label;
280  if (text.isEmpty())
281  {
282  if (command.IsNotNull())
283  {
284  try
285  {
286  text = command->GetCommand()->GetName();
287  }
288  catch (const NotDefinedException& e)
289  {
290 // StatusManager.getManager().handle(
291 // StatusUtil.newStatus(IStatus.ERROR,
292 // "Update item failed "
293 // + getId(), e));
294  BERRY_ERROR << "Update item failed " << GetId() << e.what();
295  }
296  }
297  }
298  text = UpdateMnemonic(text);
299 
300 // String keyBindingText = null;
301 // if (command != null)
302 // {
303 // TriggerSequence binding = bindingService
304 // .getBestActiveBindingFor(command);
305 // if (binding != null)
306 // {
307 // keyBindingText = binding.format();
308 // }
309 // }
310 // if (text != null)
311 // {
312 // if (keyBindingText == null)
313 // {
314 // item.setText(text);
315 // }
316 // else
317 // {
318 // item.setText(text + '\t' + keyBindingText);
319 // }
320 // }
321 
322  if (action->isChecked() != checkedState)
323  {
324  action->setChecked(checkedState);
325  }
326 
327  // allow the handler update its enablement
328  bool shouldBeEnabled = IsEnabled();
329  if (action->isEnabled() != shouldBeEnabled)
330  {
331  action->setEnabled(shouldBeEnabled);
332  }
333 }
334 
335 void CommandContributionItem::UpdateToolItem()
336 {
337  QString text = label;
338  QString tooltip = label;
339  if (text.isNull())
340  {
341  if (command.IsNotNull())
342  {
343  try
344  {
345  text = command->GetCommand()->GetName();
346  tooltip = command->GetCommand()->GetDescription();
347  if (tooltip.trimmed().isEmpty())
348  {
349  tooltip = text;
350  }
351  }
352  catch (const NotDefinedException& e)
353  {
354 // StatusManager.getManager().handle(
355 // StatusUtil.newStatus(IStatus.ERROR,
356 // "Update item failed "
357 // + getId(), e));
358  BERRY_ERROR << "Update item failed " << GetId() << e.what();
359  }
360  }
361  }
362 
363  if ((icon.isNull() || (mode & MODE_FORCE_TEXT) == MODE_FORCE_TEXT)
364  && !text.isNull())
365  {
366  action->setText(text);
367  }
368 
369  QString toolTipText = GetToolTipText(tooltip);
370  action->setToolTip(toolTipText);
371 
372  if (action->isChecked() != checkedState)
373  {
374  action->setChecked(checkedState);
375  }
376 
377  // allow the handler update its enablement
378  bool shouldBeEnabled = IsEnabled();
379  if (action->isEnabled() != shouldBeEnabled)
380  {
381  action->setEnabled(shouldBeEnabled);
382  }
383 }
384 
386 {
387  if (elementRef)
388  {
389  commandService->UnregisterElement(elementRef);
390  }
391  if (commandListener)
392  {
393  command->GetCommand()->RemoveCommandListener(commandListener.data());
394  }
395 }
396 
398 {
399  if (command)
400  {
401  command->GetCommand()->SetEnabled(menuService->GetCurrentState());
402  return command->GetCommand()->IsEnabled();
403  }
404  return false;
405 }
406 
408 {
409  if (visibleEnabled)
410  {
411  return ContributionItem::IsVisible() && this->IsEnabled();
412  }
414 }
415 
416 void CommandContributionItem::SetImages(IServiceLocator* locator,
417  const QString& iconStyle)
418 {
419  if (icon.isNull())
420  {
422  if (service)
423  {
424  icon = service->GetImage(command->GetId(), iconStyle);
425  }
426  }
427 }
428 
429 ICommandListener* CommandContributionItem::GetCommandListener()
430 {
431  if (!commandListener)
432  {
433  class MyCommandListener : public ICommandListener
434  {
435 
436  private:
438 
439  public:
440 
441  MyCommandListener(CommandContributionItem* item)
442  : item(item)
443  {}
444 
445  void CommandChanged(const SmartPointer<const CommandEvent>& commandEvent) override
446  {
447  if (commandEvent->IsHandledChanged() || commandEvent->IsEnabledChanged()
448  || commandEvent->IsDefinedChanged())
449  {
450  item->UpdateCommandProperties(commandEvent);
451  }
452  }
453 
454  };
455 
456  commandListener.reset(new MyCommandListener(this));
457  }
458  return commandListener.data();
459 }
460 
461 void CommandContributionItem::UpdateCommandProperties(const SmartPointer<
462  const CommandEvent> commandEvent)
463 {
464  if (commandEvent->IsHandledChanged())
465  {
466  dropDownMenuOverride = "";
467  }
468  if (!action)
469  {
470  return;
471  }
472  Display* display = Display::GetDefault();
473  typedef AsyncRunnable<SmartPointer<const CommandEvent>, CommandContributionItem > UpdateRunnable;
474  Poco::Runnable* update = new UpdateRunnable(this, &CommandContributionItem::UpdateCommandPropertiesInUI, commandEvent);
475  if (display->InDisplayThread())
476  {
477  update->run();
478  }
479  else
480  {
481  display->AsyncExec(update);
482  }
483 }
484 
486  const CommandEvent>& commandEvent)
487 {
488  if (commandEvent->GetCommand()->IsDefined())
489  {
490  this->Update();
491  }
492  if (commandEvent->IsEnabledChanged()
493  || commandEvent->IsHandledChanged())
494  {
495  if (visibleEnabled)
496  {
497  IContributionManager* parent = this->GetParent();
498  if (parent)
499  {
500  parent->Update(true);
501  }
502  }
503  }
504 }
505 
506 void CommandContributionItem::HandleActionDestroyed()
507 {
508  this->action = nullptr;
509 }
510 
511 bool CommandContributionItem::ShouldRestoreAppearance(const SmartPointer<IHandler>& handler)
512 {
513  // if no handler or handler doesn't implement IElementUpdater,
514  // restore the contributed elements
515  if (handler.IsNull())
516  return true;
517 
518  if (!(handler.Cast<IElementUpdater>()))
519  return true;
520 
521  // special case, if its HandlerProxy, then check the actual handler
522 // if (handler instanceof HandlerProxy) {
523 // HandlerProxy handlerProxy = (HandlerProxy) handler;
524 // IHandler actualHandler = handlerProxy.getHandler();
525 // return shouldRestoreAppearance(actualHandler);
526 // }
527  return false;
528 }
529 
530 SmartPointer<ParameterizedCommand> CommandContributionItem::GetCommand() const
531 {
532  return command;
533 }
534 
535 void CommandContributionItem::CreateCommand(const QString &commandId,
536  const QHash<QString,Object::Pointer> &parameters)
537 {
538  if (commandId.isEmpty())
539  {
540 // StatusManager.getManager().handle(StatusUtil.newStatus(IStatus.ERROR,
541 // "Unable to create menu item \"" + getId()
542 // + "\", no command id", null));
543  BERRY_ERROR << "Unable to create menu item \"" << this->GetId().toStdString()
544  << "\", no command id";
545  return;
546  }
547  Command::Pointer cmd = commandService->GetCommand(commandId);
548  if (!cmd->IsDefined())
549  {
550 // StatusManager.getManager().handle(StatusUtil.newStatus(
551 // IStatus.ERROR, "Unable to create menu item \"" + getId()
552 // + "\", command \"" + commandId + "\" not defined", null));
553  BERRY_ERROR << "Unable to create menu item \"" << this->GetId().toStdString()
554  << "\", command \"" << commandId.toStdString() << "\" not defined";
555  return;
556  }
557 
558  command = ParameterizedCommand::GenerateCommand(cmd, parameters);
559 }
560 
561 QString CommandContributionItem::GetToolTipText(const QString& text) const
562 {
563  QString tooltipText = tooltip;
564  if (tooltip.isNull())
565  {
566  if (!text.isNull())
567  {
568  tooltipText = text;
569  }
570  else
571  {
572  tooltipText = "";
573  }
574  }
575 
576 // TriggerSequence activeBinding = bindingService
577 // .getBestActiveBindingFor(command);
578 // if (activeBinding != null && !activeBinding.isEmpty())
579 // {
580 // String acceleratorText = activeBinding.format();
581 // if (acceleratorText != null
582 // && acceleratorText.length() != 0)
583 // {
584 // tooltipText = NLS.bind(CommandMessages.Tooltip_Accelerator,
585 // tooltipText, acceleratorText);
586 // }
587 // }
588 
589  return tooltipText;
590 }
591 
592 QString CommandContributionItem::UpdateMnemonic(const QString &s)
593 {
594  if (mnemonic.isNull() || s.isEmpty())
595  {
596  return s;
597  }
598 
599  int idx = s.indexOf(mnemonic);
600  if (idx == -1)
601  {
602  return s;
603  }
604 
605  return s.left(idx) + '&' + s.mid(idx);
606 }
607 
608 //SmartPointer<IUIElementListener> CommandContributionItem::GetItemListener()
609 //{
610 // if (!itemListener)
611 // {
612 // itemListener = new CommandUIElementListener(this);
613 // }
614 // return itemListener;
615 //}
616 
617 void CommandContributionItem::HandleWidgetSelection()
618 {
619 // // Special check for ToolBar dropdowns...
620 // if (this->OpenDropDownMenu(event))
621 // //return;
622 
623  if ((style & STYLE_CHECK) != 0)
624  {
625  checkedState = action->isChecked();
626  }
627 
628  try
629  {
630  handlerService->ExecuteCommand(command, UIElement::Pointer(nullptr));
631  }
632  catch (const ExecutionException& e)
633  {
634  WorkbenchPlugin::Log("Failed to execute item " + GetId(), e);
635  }
636  catch (const NotDefinedException& e)
637  {
638  WorkbenchPlugin::Log("Failed to execute item " + GetId(), e);
639  }
640  catch (const NotEnabledException& e)
641  {
642  WorkbenchPlugin::Log("Failed to execute item " + GetId(), e);
643  }
644  catch (const NotHandledException& e)
645  {
646  WorkbenchPlugin::Log("Failed to execute item " + GetId(), e);
647  }
648 }
649 
650 //TODO Tool item drop down menu contributions
651 //bool CommandContributionItem::OpenDropDownMenu(SmartPointer<GuiTk::Event> event)
652 //{
653 //Widget item = event.widget;
654 //if (item != null)
655 //{
656 // int style = item.getStyle();
657 // if ((style & SWT.DROP_DOWN) != 0)
658 // {
659 // if (event.detail == 4)
660 // { // on drop-down button
661 // ToolItem ti = (ToolItem) item;
662 //
663 // final MenuManager menuManager = new MenuManager();
664 // Menu menu = menuManager.createContextMenu(ti.getParent());
665 // if (workbenchHelpSystem != null)
666 // {
667 // workbenchHelpSystem.setHelp(menu, helpContextId);
668 // }
669 // menuManager.addMenuListener(new IMenuListener()
670 // {
671 // public void menuAboutToShow(IMenuManager manager)
672 // {
673 // String id = getId();
674 // if (dropDownMenuOverride != null)
675 // {
676 // id = dropDownMenuOverride;
677 // }
678 // menuService.populateContributionManager(
679 // menuManager, "menu:" + id); //$NON-NLS-1$
680 // }
681 // });
682 //
683 // // position the menu below the drop down item
684 // Point point = ti.getParent().toDisplay(
685 // new Point(event.x, event.y));
686 // menu.setLocation(point.x, point.y); // waiting for SWT
687 // // 0.42
688 // menu.setVisible(true);
689 // return true; // we don't fire the action
690 // }
691 // }
692 //}
693 //
694 //return false;
695 //}
696 
697 void CommandContributionItem::SetIcon(const QIcon &icon)
698 {
699  this->icon = icon;
700  this->UpdateIcons();
701 }
702 
703 void CommandContributionItem::UpdateIcons()
704 {
705  action->setIcon(icon);
706 }
707 
708 void CommandContributionItem::SetText(const QString &text)
709 {
710  label = text;
711  this->Update();
712 }
713 
714 void CommandContributionItem::SetChecked(bool checked)
715 {
716  if (checkedState == checked)
717  {
718  return;
719  }
720  checkedState = checked;
721  action->setChecked(checkedState);
722 }
723 
724 void CommandContributionItem::SetToolTip(const QString &text)
725 {
726  tooltip = text;
727  action->setToolTip(text);
728 }
729 
730 }
static MsgHandler handler
Definition: usUtils.cpp:261
virtual void Update(bool force)=0
bool IsVisible() const override
virtual void UnregisterElement(const SmartPointer< IElementReference > &elementReference)=0
void UpdateCommandPropertiesInUI(const SmartPointer< const CommandEvent > &commandEvent)
virtual QIcon GetImage(const QString &commandId)=0
void Fill(QMenu *parent, QAction *before) override
static Display * GetDefault()
Implements transparent reference counting.
virtual Object::Pointer ExecuteCommand(const QString &commandId, const SmartPointer< const UIElement > &uielement)=0
static ParameterizedCommand::Pointer GenerateCommand(const SmartPointer< Command > command, const QHash< QString, Object::Pointer > &parameters)
#define BERRY_ERROR
Definition: berryLog.h:26
IContributionManager * GetParent() const
berry::SmartPointer< Self > Pointer
Definition: berryObject.h:88
virtual SmartPointer< Command > GetCommand(const QString &commandId) const =0
CommandContributionItem(const SmartPointer< CommandContributionItemParameter > &contributionParameters)
virtual SmartPointer< IEvaluationContext > GetCurrentState() const =0
QString GetId() const override