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