1
// TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2017, 2019, 2023 - TortoiseGit
4 // Copyright (C) 2017 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "NativeRibbonApp.h"
24 CNativeRibbonApp::CNativeRibbonApp(CFrameWnd
* pFrame
, IUIFramework
* pFramework
)
26 , m_pFramework(pFramework
)
30 CNativeRibbonApp::~CNativeRibbonApp()
32 ASSERT(m_cRefCount
== 0);
35 STDMETHODIMP
CNativeRibbonApp::QueryInterface(REFIID riid
, void **ppvObject
)
37 if (riid
== IID_IUnknown
)
40 *ppvObject
= static_cast<IUICommandHandler
*>(this);
43 else if (riid
== __uuidof(IUIApplication
))
46 *ppvObject
= static_cast<IUIApplication
*>(this);
49 else if (riid
== __uuidof(IUICommandHandler
))
52 *ppvObject
= static_cast<IUICommandHandler
*>(this);
61 STDMETHODIMP_(ULONG
) CNativeRibbonApp::AddRef(void)
63 return InterlockedIncrement(&m_cRefCount
);
66 STDMETHODIMP_(ULONG
) CNativeRibbonApp::Release(void)
68 return InterlockedDecrement(&m_cRefCount
);
71 STDMETHODIMP
CNativeRibbonApp::OnViewChanged(UINT32
/*viewId*/, UI_VIEWTYPE typeID
, IUnknown
* view
, UI_VIEWVERB verb
, INT32
/*uReasonCode*/)
73 if (typeID
== UI_VIEWTYPE_RIBBON
)
75 if (verb
== UI_VIEWVERB_CREATE
)
77 if (!m_SettingsFileName
.IsEmpty())
79 CComQIPtr
<IUIRibbon
> ribbonView(view
);
81 LoadRibbonViewSettings(ribbonView
, m_SettingsFileName
);
84 m_pFrame
->RecalcLayout();
86 else if (verb
== UI_VIEWVERB_DESTROY
)
88 CComQIPtr
<IUIRibbon
> ribbonView(view
);
90 SaveRibbonViewSettings(ribbonView
, m_SettingsFileName
);
92 else if (verb
== UI_VIEWVERB_SIZE
)
93 m_pFrame
->RecalcLayout();
99 STDMETHODIMP
CNativeRibbonApp::OnCreateUICommand(UINT32 commandId
, UI_COMMANDTYPE typeID
, IUICommandHandler
** commandHandler
)
101 m_commandIds
.push_back(commandId
);
102 if (typeID
== UI_COMMANDTYPE_COLLECTION
)
103 m_collectionCommandIds
.push_back(commandId
);
105 return QueryInterface(IID_PPV_ARGS(commandHandler
));
108 STDMETHODIMP
CNativeRibbonApp::OnDestroyUICommand(UINT32 commandId
, UI_COMMANDTYPE
/*typeID*/, IUICommandHandler
* /*commandHandler*/)
110 m_commandIds
.remove(commandId
);
115 STDMETHODIMP
CNativeRibbonApp::Execute(UINT32 commandId
, UI_EXECUTIONVERB verb
, const PROPERTYKEY
* key
, const PROPVARIANT
* currentValue
, IUISimplePropertySet
* /*commandExecutionProperties*/)
117 if (verb
== UI_EXECUTIONVERB_EXECUTE
)
119 if (key
&& IsEqualPropertyKey(*key
, UI_PKEY_SelectedItem
))
121 CComPtr
<IUICollection
> items
= GetUICommandItemsSource(commandId
);
122 UINT32 selectedItemIdx
= 0;
123 UIPropertyToUInt32(UI_PKEY_SelectedItem
, *currentValue
, &selectedItemIdx
);
125 items
->GetCount(&count
);
127 if (selectedItemIdx
< count
)
129 CComPtr
<IUnknown
> selectedItemUnk
;
130 items
->GetItem(selectedItemIdx
, &selectedItemUnk
);
131 CComQIPtr
<IUISimplePropertySet
> selectedItemPropSet(selectedItemUnk
);
132 if (selectedItemPropSet
)
133 m_pFrame
->PostMessage(WM_COMMAND
, GetCommandIdProperty(selectedItemPropSet
));
137 m_pFrame
->PostMessage(WM_COMMAND
, commandId
);
145 class CRibbonCmdUI
: public CCmdUI
153 CRibbonCmdUI(int commandId
)
156 , m_bCheckChanged(FALSE
)
161 virtual void Enable(BOOL bOn
)
164 m_bEnableChanged
= TRUE
;
167 virtual void SetCheck(int nCheck
)
170 m_bCheckChanged
= TRUE
;
173 virtual void SetText(LPCWSTR lpszText
)
179 STDMETHODIMP
CNativeRibbonApp::UpdateProperty(UINT32 commandId
, REFPROPERTYKEY key
, const PROPVARIANT
* /*currentValue*/, PROPVARIANT
* newValue
)
181 if (key
== UI_PKEY_TooltipTitle
)
184 if (!str
.LoadString(commandId
))
187 int nIndex
= str
.Find(L
'\n');
191 str
= str
.Mid(nIndex
+ 1);
195 if (m_pFrame
!= NULL
&& (CKeyboardManager::FindDefaultAccelerator(commandId
, strLabel
, m_pFrame
, TRUE
) ||
196 CKeyboardManager::FindDefaultAccelerator(commandId
, strLabel
, m_pFrame
->GetActiveFrame(), FALSE
)))
203 return UIInitPropertyFromString(UI_PKEY_TooltipTitle
, str
, newValue
);
205 else if (key
== UI_PKEY_TooltipDescription
)
208 if (!str
.LoadString(commandId
))
211 int nIndex
= str
.Find(L
'\n');
215 str
= str
.Left(nIndex
);
217 return UIInitPropertyFromString(UI_PKEY_TooltipDescription
, str
, newValue
);
219 else if (key
== UI_PKEY_Enabled
)
221 CRibbonCmdUI
ui(commandId
);
222 ui
.DoUpdate(m_pFrame
, TRUE
);
224 return UIInitPropertyFromBoolean(UI_PKEY_Enabled
, ui
.m_bOn
, newValue
);
226 else if (key
== UI_PKEY_BooleanValue
)
228 CRibbonCmdUI
ui(commandId
);
229 ui
.DoUpdate(m_pFrame
, TRUE
);
231 return UIInitPropertyFromBoolean(UI_PKEY_BooleanValue
, ui
.m_nCheck
, newValue
);
233 else if (key
== UI_PKEY_SelectedItem
)
235 CComPtr
<IUICollection
> items
= GetUICommandItemsSource(commandId
);
240 items
->GetCount(&count
);
241 for (UINT32 idx
= 0; idx
< count
; idx
++)
243 CComPtr
<IUnknown
> item
;
244 items
->GetItem(idx
, &item
);
246 CComQIPtr
<IUISimplePropertySet
> simplePropertySet(item
);
247 if (simplePropertySet
)
249 PROPVARIANT var
= { 0 };
251 simplePropertySet
->GetValue(UI_PKEY_CommandId
, &var
);
252 UIPropertyToUInt32(UI_PKEY_CommandId
, var
, &uiVal
);
254 CRibbonCmdUI
ui(uiVal
);
255 ui
.DoUpdate(m_pFrame
, TRUE
);
259 UIInitPropertyFromUInt32(UI_PKEY_SelectedItem
, idx
, newValue
);
266 UIInitPropertyFromUInt32(UI_PKEY_SelectedItem
, static_cast<UINT
>(-1), newValue
);
274 HRESULT
CNativeRibbonApp::SaveRibbonViewSettings(IUIRibbon
* pRibbonView
, const CString
& fileName
)
276 CComPtr
<IStream
> stream
;
277 HRESULT hr
= SHCreateStreamOnFileEx(fileName
, STGM_WRITE
| STGM_CREATE
, FILE_ATTRIBUTE_NORMAL
, TRUE
, nullptr, &stream
);
281 hr
= pRibbonView
->SaveSettingsToStream(stream
);
288 hr
= stream
->Commit(STGC_DEFAULT
);
293 HRESULT
CNativeRibbonApp::LoadRibbonViewSettings(IUIRibbon
* pRibbonView
, const CString
& fileName
)
295 CComPtr
<IStream
> stream
;
296 HRESULT hr
= SHCreateStreamOnFileEx(fileName
, STGM_READ
, FILE_ATTRIBUTE_NORMAL
, FALSE
, nullptr, &stream
);
300 hr
= pRibbonView
->LoadSettingsFromStream(stream
);
305 CComPtr
<IUICollection
> CNativeRibbonApp::GetUICommandItemsSource(UINT commandId
)
307 PROPVARIANT prop
= { 0 };
309 m_pFramework
->GetUICommandProperty(commandId
, UI_PKEY_ItemsSource
, &prop
);
311 CComPtr
<IUICollection
> uiCollection
;
312 UIPropertyToInterface(UI_PKEY_ItemsSource
, prop
, &uiCollection
);
313 PropVariantClear(&prop
);
318 void CNativeRibbonApp::SetUICommandItemsSource(UINT commandId
, IUICollection
* pItems
)
320 PROPVARIANT prop
= { 0 };
322 UIInitPropertyFromInterface(UI_PKEY_ItemsSource
, pItems
, &prop
);
324 m_pFramework
->SetUICommandProperty(commandId
, UI_PKEY_ItemsSource
, prop
);
326 PropVariantClear(&prop
);
329 UINT
CNativeRibbonApp::GetCommandIdProperty(IUISimplePropertySet
* propertySet
)
331 PROPVARIANT var
= { 0 };
332 UINT32 commandId
= 0;
334 if (propertySet
->GetValue(UI_PKEY_CommandId
, &var
) == S_OK
)
335 UIPropertyToUInt32(UI_PKEY_CommandId
, var
, &commandId
);
340 void CNativeRibbonApp::UpdateCmdUI(BOOL bDisableIfNoHandler
)
342 for (auto it
= m_commandIds
.begin(); it
!= m_commandIds
.end(); ++it
)
344 CRibbonCmdUI
ui(*it
);
345 ui
.DoUpdate(m_pFrame
, bDisableIfNoHandler
);
346 if (ui
.m_bEnableChanged
)
348 PROPVARIANT val
= { 0 };
349 UIInitPropertyFromBoolean(UI_PKEY_Enabled
, ui
.m_bOn
, &val
);
350 m_pFramework
->SetUICommandProperty(*it
, UI_PKEY_Enabled
, val
);
353 if (ui
.m_bCheckChanged
)
355 PROPVARIANT val
= { 0 };
356 UIInitPropertyFromBoolean(UI_PKEY_BooleanValue
, ui
.m_nCheck
, &val
);
357 m_pFramework
->SetUICommandProperty(*it
, UI_PKEY_BooleanValue
, val
);
361 for (auto it
= m_collectionCommandIds
.begin(); it
!= m_collectionCommandIds
.end(); ++it
)
363 PROPVARIANT currentValue
= { 0 };
364 PROPVARIANT newValue
= { 0 };
366 UpdateProperty(*it
, UI_PKEY_SelectedItem
, ¤tValue
, &newValue
);
367 m_pFramework
->SetUICommandProperty(*it
, UI_PKEY_SelectedItem
, newValue
);
371 int CNativeRibbonApp::GetRibbonHeight()
373 CComPtr
<IUIRibbon
> pRibbon
;
374 if (SUCCEEDED(m_pFramework
->GetView(0, IID_PPV_ARGS(&pRibbon
))))
377 pRibbon
->GetHeight(&cy
);
378 return static_cast<int>(cy
);
384 class UIDynamicCommandItem
: public IUISimplePropertySet
390 CComPtr
<IUIImage
> m_Image
;
393 class UIDynamicCommandItem(int commandId
, LPCWSTR label
, IUIImage
* image
)
396 , m_CommandId(commandId
)
401 STDMETHOD(QueryInterface
)(REFIID riid
, void** ppvObject
)
403 if (riid
== __uuidof(IUnknown
))
406 *ppvObject
= static_cast<IUnknown
*>(this);
409 else if (riid
== __uuidof(IUISimplePropertySet
))
412 *ppvObject
= static_cast<IUISimplePropertySet
*>(this);
415 return E_NOINTERFACE
;
418 STDMETHOD_(ULONG
, AddRef
)(void)
420 return InterlockedIncrement(&m_RefCount
);
423 STDMETHOD_(ULONG
, Release
)(void)
425 if (InterlockedDecrement(&m_RefCount
) == 0)
433 STDMETHOD(GetValue
)(REFPROPERTYKEY key
, PROPVARIANT
* value
)
435 if (key
== UI_PKEY_Label
)
436 return UIInitPropertyFromString(key
, m_Label
, value
);
437 else if (key
== UI_PKEY_CommandId
)
438 return UIInitPropertyFromUInt32(UI_PKEY_CommandId
, m_CommandId
, value
);
439 else if (key
== UI_PKEY_ItemImage
)
440 return UIInitPropertyFromInterface(UI_PKEY_ItemImage
, m_Image
, value
);
445 void CNativeRibbonApp::SetItems(UINT cmdId
, const std::list
<CNativeRibbonDynamicItemInfo
>& items
)
447 CComPtr
<IUICollection
> uiCollection
= GetUICommandItemsSource(cmdId
);
451 CComPtr
<IUIImageFromBitmap
> imageFactory
;
452 imageFactory
.CoCreateInstance(__uuidof(UIRibbonImageFromBitmapFactory
));
456 uiCollection
->GetCount(&count
);
457 for (const auto & item
: items
)
459 CComPtr
<IUIImage
> image
;
460 if (imageFactory
&& item
.GetImageId() > 0)
462 HBITMAP hbm
= static_cast<HBITMAP
>(LoadImage( AfxGetResourceHandle(), MAKEINTRESOURCE(item
.GetImageId()), IMAGE_BITMAP
, 0, 0, LR_CREATEDIBSECTION
));
463 imageFactory
->CreateImage(hbm
, UI_OWNERSHIP_TRANSFER
, &image
);
467 uiCollection
->Replace(idx
, new UIDynamicCommandItem(item
.GetCommandId(), item
.GetLabel(), image
));
469 uiCollection
->Add(new UIDynamicCommandItem(item
.GetCommandId(), item
.GetLabel(), image
));
473 for (; idx
< count
; idx
++)
475 uiCollection
->RemoveAt(idx
);
477 SetUICommandItemsSource(cmdId
, uiCollection
);