1 // Copyright (C) 2017 - TortoiseGit
2 // Copyright (C) 2017 - TortoiseSVN
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software Foundation,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "NativeRibbonApp.h"
22 CNativeRibbonApp::CNativeRibbonApp(CFrameWnd
* pFrame
, IUIFramework
* pFramework
)
24 , m_pFramework(pFramework
)
29 CNativeRibbonApp::~CNativeRibbonApp()
31 ASSERT(m_cRefCount
== 0);
34 STDMETHODIMP
CNativeRibbonApp::QueryInterface(REFIID riid
, void **ppvObject
)
36 if (riid
== IID_IUnknown
)
39 *ppvObject
= (IUICommandHandler
*)this;
42 else if (riid
== __uuidof(IUIApplication
))
45 *ppvObject
= (IUIApplication
*)this;
48 else if (riid
== __uuidof(IUICommandHandler
))
51 *ppvObject
= (IUICommandHandler
*)this;
60 STDMETHODIMP_(ULONG
) CNativeRibbonApp::AddRef(void)
62 return InterlockedIncrement(&m_cRefCount
);
65 STDMETHODIMP_(ULONG
) CNativeRibbonApp::Release(void)
67 return InterlockedDecrement(&m_cRefCount
);
70 STDMETHODIMP
CNativeRibbonApp::OnViewChanged(UINT32
/*viewId*/, UI_VIEWTYPE typeID
, IUnknown
* view
, UI_VIEWVERB verb
, INT32
/*uReasonCode*/)
72 if (typeID
== UI_VIEWTYPE_RIBBON
)
74 if (verb
== UI_VIEWVERB_CREATE
)
76 if (!m_SettingsFileName
.IsEmpty())
78 CComQIPtr
<IUIRibbon
> ribbonView(view
);
80 LoadRibbonViewSettings(ribbonView
, m_SettingsFileName
);
83 m_pFrame
->RecalcLayout();
85 else if (verb
== UI_VIEWVERB_DESTROY
)
87 CComQIPtr
<IUIRibbon
> ribbonView(view
);
89 SaveRibbonViewSettings(ribbonView
, m_SettingsFileName
);
91 else if (verb
== UI_VIEWVERB_SIZE
)
92 m_pFrame
->RecalcLayout();
98 STDMETHODIMP
CNativeRibbonApp::OnCreateUICommand(UINT32 commandId
, UI_COMMANDTYPE typeID
, IUICommandHandler
** commandHandler
)
100 m_commandIds
.push_back(commandId
);
101 if (typeID
== UI_COMMANDTYPE_COLLECTION
)
102 m_collectionCommandIds
.push_back(commandId
);
104 return QueryInterface(IID_PPV_ARGS(commandHandler
));
107 STDMETHODIMP
CNativeRibbonApp::OnDestroyUICommand(UINT32 commandId
, UI_COMMANDTYPE
/*typeID*/, IUICommandHandler
* /*commandHandler*/)
109 m_commandIds
.remove(commandId
);
114 STDMETHODIMP
CNativeRibbonApp::Execute(UINT32 commandId
, UI_EXECUTIONVERB verb
, const PROPERTYKEY
* key
, const PROPVARIANT
* currentValue
, IUISimplePropertySet
* /*commandExecutionProperties*/)
116 if (verb
== UI_EXECUTIONVERB_EXECUTE
)
118 if (key
&& IsEqualPropertyKey(*key
, UI_PKEY_SelectedItem
))
120 CComPtr
<IUICollection
> items
= GetUICommandItemsSource(commandId
);
121 UINT32 selectedItemIdx
= 0;
122 UIPropertyToUInt32(UI_PKEY_SelectedItem
, *currentValue
, &selectedItemIdx
);
124 items
->GetCount(&count
);
126 if (selectedItemIdx
< count
)
128 CComPtr
<IUnknown
> selectedItemUnk
;
129 items
->GetItem(selectedItemIdx
, &selectedItemUnk
);
130 CComQIPtr
<IUISimplePropertySet
> selectedItemPropSet(selectedItemUnk
);
131 if (selectedItemPropSet
)
132 m_pFrame
->PostMessage(WM_COMMAND
, GetCommandIdProperty(selectedItemPropSet
));
136 m_pFrame
->PostMessage(WM_COMMAND
, commandId
);
144 class CRibbonCmdUI
: public CCmdUI
152 CRibbonCmdUI(int commandId
)
155 , m_bCheckChanged(FALSE
)
160 virtual void Enable(BOOL bOn
)
163 m_bEnableChanged
= TRUE
;
166 virtual void SetCheck(int nCheck
)
169 m_bCheckChanged
= TRUE
;
172 virtual void SetText(LPCTSTR lpszText
)
178 STDMETHODIMP
CNativeRibbonApp::UpdateProperty(UINT32 commandId
, REFPROPERTYKEY key
, const PROPVARIANT
* /*currentValue*/, PROPVARIANT
* newValue
)
180 if (key
== UI_PKEY_TooltipTitle
)
183 if (!str
.LoadString(commandId
))
186 int nIndex
= str
.Find(L
'\n');
190 str
= str
.Mid(nIndex
+ 1);
194 if (m_pFrame
!= NULL
&& (CKeyboardManager::FindDefaultAccelerator(commandId
, strLabel
, m_pFrame
, TRUE
) ||
195 CKeyboardManager::FindDefaultAccelerator(commandId
, strLabel
, m_pFrame
->GetActiveFrame(), FALSE
)))
202 return UIInitPropertyFromString(UI_PKEY_TooltipTitle
, str
, newValue
);
204 else if (key
== UI_PKEY_TooltipDescription
)
207 if (!str
.LoadString(commandId
))
210 int nIndex
= str
.Find(L
'\n');
214 str
= str
.Left(nIndex
);
216 return UIInitPropertyFromString(UI_PKEY_TooltipDescription
, str
, newValue
);
218 else if (key
== UI_PKEY_Enabled
)
220 CRibbonCmdUI
ui(commandId
);
221 ui
.DoUpdate(m_pFrame
, TRUE
);
223 return UIInitPropertyFromBoolean(UI_PKEY_Enabled
, ui
.m_bOn
, newValue
);
225 else if (key
== UI_PKEY_BooleanValue
)
227 CRibbonCmdUI
ui(commandId
);
228 ui
.DoUpdate(m_pFrame
, TRUE
);
230 return UIInitPropertyFromBoolean(UI_PKEY_BooleanValue
, ui
.m_nCheck
, newValue
);
232 else if (key
== UI_PKEY_SelectedItem
)
234 CComPtr
<IUICollection
> items
= GetUICommandItemsSource(commandId
);
239 items
->GetCount(&count
);
240 for (UINT32 idx
= 0; idx
< count
; idx
++)
242 CComPtr
<IUnknown
> item
;
243 items
->GetItem(idx
, &item
);
245 CComQIPtr
<IUISimplePropertySet
> simplePropertySet(item
);
246 if (simplePropertySet
)
248 PROPVARIANT var
= { 0 };
250 simplePropertySet
->GetValue(UI_PKEY_CommandId
, &var
);
251 UIPropertyToUInt32(UI_PKEY_CommandId
, var
, &uiVal
);
253 CRibbonCmdUI
ui(uiVal
);
254 ui
.DoUpdate(m_pFrame
, TRUE
);
258 UIInitPropertyFromUInt32(UI_PKEY_SelectedItem
, idx
, newValue
);
265 UIInitPropertyFromUInt32(UI_PKEY_SelectedItem
, (UINT
)-1, newValue
);
273 HRESULT
CNativeRibbonApp::SaveRibbonViewSettings(IUIRibbon
* pRibbonView
, const CString
& fileName
)
275 CComPtr
<IStream
> stream
;
276 HRESULT hr
= SHCreateStreamOnFileEx(fileName
, STGM_WRITE
| STGM_CREATE
, FILE_ATTRIBUTE_NORMAL
, TRUE
, nullptr, &stream
);
280 hr
= pRibbonView
->SaveSettingsToStream(stream
);
287 hr
= stream
->Commit(STGC_DEFAULT
);
292 HRESULT
CNativeRibbonApp::LoadRibbonViewSettings(IUIRibbon
* pRibbonView
, const CString
& fileName
)
294 CComPtr
<IStream
> stream
;
295 HRESULT hr
= SHCreateStreamOnFileEx(fileName
, STGM_READ
, FILE_ATTRIBUTE_NORMAL
, FALSE
, nullptr, &stream
);
299 hr
= pRibbonView
->LoadSettingsFromStream(stream
);
304 CComPtr
<IUICollection
> CNativeRibbonApp::GetUICommandItemsSource(UINT commandId
)
306 PROPVARIANT prop
= { 0 };
308 m_pFramework
->GetUICommandProperty(commandId
, UI_PKEY_ItemsSource
, &prop
);
310 CComPtr
<IUICollection
> uiCollection
;
311 UIPropertyToInterface(UI_PKEY_ItemsSource
, prop
, &uiCollection
);
312 PropVariantClear(&prop
);
317 void CNativeRibbonApp::SetUICommandItemsSource(UINT commandId
, IUICollection
* pItems
)
319 PROPVARIANT prop
= { 0 };
321 UIInitPropertyFromInterface(UI_PKEY_ItemsSource
, pItems
, &prop
);
323 m_pFramework
->SetUICommandProperty(commandId
, UI_PKEY_ItemsSource
, prop
);
325 PropVariantClear(&prop
);
328 UINT
CNativeRibbonApp::GetCommandIdProperty(IUISimplePropertySet
* propertySet
)
330 PROPVARIANT var
= { 0 };
331 UINT32 commandId
= 0;
333 if (propertySet
->GetValue(UI_PKEY_CommandId
, &var
) == S_OK
)
334 UIPropertyToUInt32(UI_PKEY_CommandId
, var
, &commandId
);
339 void CNativeRibbonApp::UpdateCmdUI(BOOL bDisableIfNoHandler
)
341 for (auto it
= m_commandIds
.begin(); it
!= m_commandIds
.end(); ++it
)
343 CRibbonCmdUI
ui(*it
);
344 ui
.DoUpdate(m_pFrame
, bDisableIfNoHandler
);
345 if (ui
.m_bEnableChanged
)
347 PROPVARIANT val
= { 0 };
348 UIInitPropertyFromBoolean(UI_PKEY_Enabled
, ui
.m_bOn
, &val
);
349 m_pFramework
->SetUICommandProperty(*it
, UI_PKEY_Enabled
, val
);
352 if (ui
.m_bCheckChanged
)
354 PROPVARIANT val
= { 0 };
355 UIInitPropertyFromBoolean(UI_PKEY_BooleanValue
, ui
.m_nCheck
, &val
);
356 m_pFramework
->SetUICommandProperty(*it
, UI_PKEY_BooleanValue
, val
);
360 for (auto it
= m_collectionCommandIds
.begin(); it
!= m_collectionCommandIds
.end(); ++it
)
362 PROPVARIANT currentValue
= { 0 };
363 PROPVARIANT newValue
= { 0 };
365 UpdateProperty(*it
, UI_PKEY_SelectedItem
, ¤tValue
, &newValue
);
366 m_pFramework
->SetUICommandProperty(*it
, UI_PKEY_SelectedItem
, newValue
);
370 int CNativeRibbonApp::GetRibbonHeight()
372 CComPtr
<IUIRibbon
> pRibbon
;
373 if (SUCCEEDED(m_pFramework
->GetView(0, IID_PPV_ARGS(&pRibbon
))))
376 pRibbon
->GetHeight(&cy
);
383 class UIDynamicCommandItem
: public IUISimplePropertySet
389 CComPtr
<IUIImage
> m_Image
;
392 class UIDynamicCommandItem(int commandId
, LPCWSTR label
, IUIImage
* image
)
395 , m_CommandId(commandId
)
400 STDMETHOD(QueryInterface
)(REFIID riid
, void** ppvObject
)
402 if (riid
== __uuidof(IUnknown
))
405 *ppvObject
= (IUnknown
*)this;
408 else if (riid
== __uuidof(IUISimplePropertySet
))
411 *ppvObject
= (IUISimplePropertySet
*)this;
414 return E_NOINTERFACE
;
417 STDMETHOD_(ULONG
, AddRef
)(void)
419 return InterlockedIncrement(&m_RefCount
);
422 STDMETHOD_(ULONG
, Release
)(void)
424 if (InterlockedDecrement(&m_RefCount
) == 0)
432 STDMETHOD(GetValue
)(REFPROPERTYKEY key
, PROPVARIANT
* value
)
434 if (key
== UI_PKEY_Label
)
435 return UIInitPropertyFromString(key
, m_Label
, value
);
436 else if (key
== UI_PKEY_CommandId
)
437 return UIInitPropertyFromUInt32(UI_PKEY_CommandId
, m_CommandId
, value
);
438 else if (key
== UI_PKEY_ItemImage
)
439 return UIInitPropertyFromInterface(UI_PKEY_ItemImage
, m_Image
, value
);
444 void CNativeRibbonApp::SetItems(UINT cmdId
, const std::list
<CNativeRibbonDynamicItemInfo
>& items
)
446 CComPtr
<IUICollection
> uiCollection
= GetUICommandItemsSource(cmdId
);
450 CComPtr
<IUIImageFromBitmap
> imageFactory
;
451 imageFactory
.CoCreateInstance(__uuidof(UIRibbonImageFromBitmapFactory
));
455 uiCollection
->GetCount(&count
);
456 for (const auto & item
: items
)
458 CComPtr
<IUIImage
> image
;
459 if (imageFactory
&& item
.GetImageId() > 0)
461 HBITMAP hbm
= (HBITMAP
)LoadImage( AfxGetResourceHandle(), MAKEINTRESOURCE(item
.GetImageId()), IMAGE_BITMAP
, 0, 0, LR_CREATEDIBSECTION
);
462 imageFactory
->CreateImage(hbm
, UI_OWNERSHIP_TRANSFER
, &image
);
466 uiCollection
->Replace(idx
, new UIDynamicCommandItem(item
.GetCommandId(), item
.GetLabel(), image
));
468 uiCollection
->Add(new UIDynamicCommandItem(item
.GetCommandId(), item
.GetLabel(), image
));
472 for (; idx
< count
; idx
++)
474 uiCollection
->RemoveAt(idx
);
476 SetUICommandItemsSource(cmdId
, uiCollection
);