1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiSource Program Utilities
4 * Copyright (C) 1998 AbiSource, Inc.
5 *
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.
10 *
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.
15 *
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
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA.
20 */
21
22 #define WIN32_LEAN_AND_MEAN
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <windows.h>
29 #include <commctrl.h> // includes the common control header
30
31 #include "ut_assert.h"
32 #include "ut_debugmsg.h"
33 #include "ut_vector.h"
34 #include "ut_Win32OS.h"
35 #include "ev_Win32Toolbar.h"
36 #include "xap_Win32App.h"
37 #include "xap_Frame.h"
38 #include "xap_Win32FrameImpl.h"
39 #include "ev_Toolbar_Actions.h"
40 #include "ev_Toolbar_Layouts.h"
41 #include "ev_Toolbar_Labels.h"
42 #include "ev_Toolbar_Control.h"
43 #include "ev_EditEventMapper.h"
44 #include "xap_Win32Toolbar_Icons.h"
45 #include "xap_EncodingManager.h"
46 #include "ev_Win32Toolbar_ViewListener.h"
47 #include "xav_View.h"
48 #include "ut_xml.h"
49 #include "xap_Prefs.h"
50 // The following are for the windows font colour dialog hack
51 #include "ap_Dialog_Id.h"
52 #include "ap_Dialog_Background.h"
53 #include "fv_View.h"
54 #include "pt_PieceTable.h"
55 #include "ap_Win32Toolbar_FontCombo.h"
56 #include "ap_Win32App.h"
57 #include "ut_Win32LocaleString.h"
58
59
60 #ifndef TBSTYLE_EX_DRAWDDARROWS
61 #define TBSTYLE_EX_DRAWDDARROWS 0x00000001
62 #endif
63
64 #ifndef TB_SETEXTENDEDSTYLE
65 #define TB_SETEXTENDEDSTYLE (WM_USER + 84) // For TBSTYLE_EX_*
66 #endif
67
68 #ifndef TB_GETEXTENDEDSTYLE
69 #define TB_GETEXTENDEDSTYLE (WM_USER + 85) // For TBSTYLE_EX_*
70 #endif
71
72 #ifndef TBSTYLE_AUTOSIZE
73 #define TBSTYLE_AUTOSIZE 0x10
74 #endif
75
76 /*****************************************************************/
77
78 //
79 // Janitor class to cleanup bitmap handles at program termination.
80 // This one should really be in the anonymous namespace in this translation
81 // unit, but since we don't use namespaces...
82 //
83 class ABI_EXPORT foo_Bitmap_container
84 {
85 public: // d'tor needs to be public due to buggy MSVC compilers
86 ~foo_Bitmap_container();
87
88 static foo_Bitmap_container& instance(); // singleton
addBitmap(HBITMAP hBm)89 void addBitmap(HBITMAP hBm)
90 {
91 UT_ASSERT(hBm);
92 m_bitmaps_vector.addItem(reinterpret_cast<void*>(hBm));
93 }
94
95 private:
foo_Bitmap_container()96 foo_Bitmap_container() : m_bitmaps_vector(50) {}
97 foo_Bitmap_container(const foo_Bitmap_container&); // no impl
98 void operator=(const foo_Bitmap_container&); // no impl
99 UT_Vector m_bitmaps_vector;
100 };
101
instance()102 foo_Bitmap_container& foo_Bitmap_container::instance()
103 {
104 static foo_Bitmap_container container;
105 return container;
106 }
107
~foo_Bitmap_container()108 foo_Bitmap_container::~foo_Bitmap_container()
109 {
110 const UT_uint32 nItems = m_bitmaps_vector.getItemCount();
111 for (UT_uint32 iItem = nItems; iItem; --iItem)
112 {
113 void* p = (void*)m_bitmaps_vector.getNthItem(iItem - 1);
114 // This is really, *REALLY* bad! The same entity that created this
115 // bitmap should also be responsible to destroy it. Time permitting,
116 // refactor all this code to make it correct.
117 ::DeleteObject((HGDIOBJ)p);
118 }
119 }
120
121
122 /*****************************************************************/
123
124
EV_Win32Toolbar(XAP_Win32App * pWin32App,XAP_Frame * pFrame,const char * szToolbarLayoutName,const char * szToolbarLabelSetName)125 EV_Win32Toolbar::EV_Win32Toolbar(XAP_Win32App * pWin32App, XAP_Frame * pFrame,
126 const char * szToolbarLayoutName,
127 const char * szToolbarLabelSetName)
128 : EV_Toolbar(pWin32App->getEditMethodContainer(),
129 szToolbarLayoutName,
130 szToolbarLabelSetName),
131 m_pWin32App(pWin32App),
132 m_pWin32Frame(pFrame),
133 m_pViewListener(NULL),
134 m_lid(0), // view listener id
135 m_hwnd(0),
136 m_pFontCtrl(NULL)
137 {
138 }
139
~EV_Win32Toolbar(void)140 EV_Win32Toolbar::~EV_Win32Toolbar(void)
141 {
142 _releaseListener();
143
144 if (m_pFontCtrl)
145 delete m_pFontCtrl;
146
147 for (UT_sint32 c=0; c < m_vecOrgStylesNames.getItemCount(); c++)
148 delete m_vecOrgStylesNames.getNthItem(c);
149
150 }
151
toolbarEvent(XAP_Toolbar_Id id,UT_UCSChar * pData,UT_uint32 dataLength)152 bool EV_Win32Toolbar::toolbarEvent(XAP_Toolbar_Id id,
153 UT_UCSChar * pData,
154 UT_uint32 dataLength)
155 {
156 // user selected something from this toolbar.
157 // invoke the appropriate function.
158 // return true iff handled.
159
160 // we use this for the color dialog hack
161
162
163 const EV_Toolbar_ActionSet * pToolbarActionSet = m_pWin32App->getToolbarActionSet();
164 UT_return_val_if_fail(pToolbarActionSet,false);
165
166 const EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
167 if (!pAction)
168 return false;
169
170 AV_View * pView = m_pWin32Frame->getCurrentView();
171
172 #if 0
173 // make sure we ignore presses on "down" group buttons
174 if (pAction->getItemType() == EV_TBIT_GroupButton)
175 {
176 const char * szState = 0;
177 EV_Toolbar_ItemState tis = pAction->getToolbarItemState(pView,&szState);
178
179 if (EV_TIS_ShouldBeToggled(tis))
180 {
181 // if this assert fires, you got a click while the button is down
182 // if your widget set won't let you prevent this, handle it here
183 UT_ASSERT_HARMLESS(UT_TODO);
184
185 // can safely ignore this event
186 return true;
187 }
188 }
189 #endif
190
191 // TODO this windows font color dialog is a hack
192 // TODO true implementation requires a custom widget on the toolbar
193 if (pAction->getItemType() == EV_TBIT_ColorFore || pAction->getItemType() == EV_TBIT_ColorBack)
194 {
195 UT_UCS4String ucs4color;
196 UT_uint32 dataLength;
197 XAP_Win32FrameImpl* fimpl = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl());
198 //int id = ItemIdFromWmCommand(cmd);
199
200 UT_ASSERT(id== AP_TOOLBAR_ID_COLOR_BACK || id== AP_TOOLBAR_ID_COLOR_FORE);
201
202 const EV_Toolbar_ActionSet * pToolbarActionSet = m_pWin32App->getToolbarActionSet();
203 UT_return_val_if_fail(pToolbarActionSet,false);
204
205 const EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
206
207 if (!pAction)
208 return true;
209
210 AV_View * pView = m_pWin32Frame->getCurrentView();
211
212 const char * szMethodName = pAction->getMethodName();
213 if (!szMethodName)
214 return true;
215
216 const EV_EditMethodContainer * pEMC = m_pWin32App->getEditMethodContainer();
217 EV_EditMethod * pEM = pEMC->findEditMethodByName(szMethodName);
218
219 if (id==AP_TOOLBAR_ID_COLOR_BACK)
220 {
221 ucs4color = fimpl->m_sColorBack.ucs4_str();
222 dataLength = fimpl->m_sColorBack.size();
223 }
224 else
225 {
226 ucs4color = fimpl->m_sColorFore.ucs4_str();
227 dataLength = fimpl->m_sColorFore.size();
228 }
229
230 invokeToolbarMethod(pView,pEM, ucs4color.ucs4_str(),dataLength);
231 }
232
233 const char * szMethodName = pAction->getMethodName();
234 if (!szMethodName)
235 return false;
236
237 const EV_EditMethodContainer * pEMC = m_pWin32App->getEditMethodContainer();
238 UT_return_val_if_fail(pEMC,false);
239
240 EV_EditMethod * pEM = pEMC->findEditMethodByName(szMethodName);
241 UT_ASSERT(pEM); // make sure it's bound to something
242
243 invokeToolbarMethod(pView,pEM,pData,dataLength);
244 return true;
245 }
246
247 /*****************************************************************/
248
249 // HACK: forward declarations for subclassed controls
250 #ifdef STRICT
251 #define WHICHPROC WNDPROC
252 #else
253 #define WHICHPROC FARPROC
254 #endif
255
256 WHICHPROC s_lpfnDefCombo;
257 WHICHPROC s_lpfnDefToolBar;
258
259
260 #define COMBO_BUF_LEN 256
261
262
263
_ToolBarWndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam)264 LRESULT CALLBACK EV_Win32Toolbar::_ToolBarWndProc (HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
265 {
266 if (uMessage == WM_CTLCOLORSTATIC) {
267 if(SetBkColor((HDC) wParam, GetSysColor(COLOR_WINDOW)) == CLR_INVALID)
268 {
269 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
270 }
271 if(SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT)) == CLR_INVALID)
272 {
273 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
274 }
275 return (LRESULT) GetSysColorBrush (COLOR_WINDOW);
276 }
277
278 return (CallWindowProcW(s_lpfnDefToolBar, hWnd, uMessage, wParam, lParam));
279 }
280
_ComboWndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam)281 LRESULT CALLBACK EV_Win32Toolbar::_ComboWndProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
282 {
283 switch (uMessage)
284 {
285 /* Draws the font preview in the font selection combobox*/
286 case WM_DRAWITEM:
287 {
288 EV_Win32Toolbar * t = (EV_Win32Toolbar *) GetWindowLongPtrW(hWnd, GWLP_USERDATA);
289 UINT u = GetDlgCtrlID(hWnd);
290 XAP_Toolbar_Id id = t->ItemIdFromWmCommand(u);
291
292 if (id!=AP_TOOLBAR_ID_FMT_FONT) /* Only owner draw the font selection*/
293 {
294 UT_ASSERT_HARMLESS(0);
295 break;
296 }
297
298 DRAWITEMSTRUCT* dis = (DRAWITEMSTRUCT*)lParam;
299 if((UT_sint32)dis->itemData < 0)
300 {
301 return TRUE;
302 }
303
304 XAP_Toolbar_ControlFactory * pFactory = t->m_pWin32App->getControlFactory();
305
306 if (!t->m_pFontCtrl)
307 {
308 EV_Toolbar_Control * pControl = pFactory->getControl(t, AP_TOOLBAR_ID_FMT_FONT);
309 t->m_pFontCtrl = static_cast<AP_Win32Toolbar_FontCombo *>(pControl);
310 t->m_pFontCtrl->populate();
311 }
312
313 HFONT hFont, hUIFont;
314 LOGFONTW logfont;
315 SIZE size;
316 HFONT hfontSave;
317 UT_Win32LocaleString str;
318 const UT_GenericVector<const char*> * v = t->m_pFontCtrl->getContents();
319 str.fromUTF8 (v->getNthItem(dis->itemData));
320
321 if(dis->itemState & ODS_COMBOBOXEDIT)
322 {
323 HFONT hUIFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
324 hfontSave = (HFONT) SelectObject (dis->hDC, hUIFont);
325 ExtTextOutW(dis->hDC, dis->rcItem.left, dis->rcItem.top, ETO_OPAQUE | ETO_CLIPPED, 0, str.c_str(), str.size(), 0);
326 SelectObject (dis->hDC, hfontSave);
327 }
328 else
329 {
330 memset (&logfont, 0, sizeof (logfont));
331
332 /* Create current font */
333 logfont.lfHeight = 18;
334 logfont.lfWidth = 0;
335 logfont.lfEscapement = 0;
336 logfont.lfOrientation = 0;
337 logfont.lfWeight = FW_BOLD;
338 logfont.lfItalic = FALSE;
339 logfont.lfUnderline = FALSE;
340 logfont.lfStrikeOut = FALSE;
341 logfont.lfCharSet = DEFAULT_CHARSET;
342 logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
343 logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
344 logfont.lfQuality = DEFAULT_QUALITY;
345 logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
346 lstrcpynW(logfont.lfFaceName, str.c_str(), LF_FACESIZE);
347 hFont = CreateFontIndirectW (&logfont);
348
349 if(dis->itemState & ODS_SELECTED) /* HighLight the selected text*/
350 {
351 SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
352 SetBkColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHT));
353 FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
354 }
355 else
356 {
357 SetTextColor(dis->hDC, GetSysColor(COLOR_WINDOWTEXT));
358 SetBkColor(dis->hDC, GetSysColor(COLOR_WINDOW));
359 FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_WINDOW) );
360 }
361
362 hUIFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
363
364 /*Fontname in regular font*/
365 hfontSave = (HFONT) SelectObject (dis->hDC, hUIFont);
366 ExtTextOutW(dis->hDC, dis->rcItem.left, dis->rcItem.top, ETO_OPAQUE | ETO_CLIPPED, 0, str.c_str(), str.size(), 0);
367
368 /*Font example after the name*/
369 const wchar_t* szSample = L"AbCdEfGhIj";
370 GetTextExtentPoint32W(dis->hDC, str.c_str(), str.size(), &size);
371 SelectObject (dis->hDC, hFont);
372 ExtTextOutW(dis->hDC, dis->rcItem.left+size.cx+5, dis->rcItem.top, ETO_OPAQUE | ETO_CLIPPED, 0, szSample, wcslen(szSample), 0);
373 SelectObject (dis->hDC, hfontSave);
374 DeleteObject(hFont);
375 }
376
377 return TRUE;
378 }
379
380 case WM_MOUSEMOVE:
381 case WM_LBUTTONDOWN:
382 case WM_LBUTTONUP:
383 {
384 // relay mouse messages from the combo box to get tool tips to work
385 // TODO: similar relay needed from edit control, too??
386 // ALT: tell tooltip control to subclass for these events
387 MSG msg;
388 HWND hWndTT;
389 msg.lParam = lParam;
390 msg.wParam = wParam;
391 msg.message = uMessage;
392 msg.hwnd = hWnd;
393
394 HWND hwndToolbar = GetParent(hWnd);
395
396 hWndTT = (HWND)SendMessageW(hwndToolbar, TB_GETTOOLTIPS, 0,0);
397 SendMessageW(hWndTT, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg);
398 break;
399 }
400
401 case WM_COMMAND:
402 {
403 switch (HIWORD(wParam))
404 {
405 case CBN_SELCHANGE:
406 {
407 UT_sint32 iSelected = SendMessageW(hWnd, CB_GETCURSEL, 0, 0);
408
409 if(iSelected != -1)
410 {
411 static UT_UCSChar ucs_buf[COMBO_BUF_LEN];
412 UT_Win32LocaleString str;
413 UT_uint32 bufLength = SendMessageW(hWnd, CB_GETLBTEXTLEN, iSelected, (LPARAM)0) + 1;
414 wchar_t* buf = (wchar_t*)g_try_malloc(bufLength * sizeof (wchar_t));
415 UT_uint32 dataLength = SendMessageW(hWnd, CB_GETLBTEXT, iSelected, (LPARAM)buf);
416 str.fromLocale (buf);
417
418 UT_UCS4_strcpy_utf8_char(ucs_buf, str.utf8_str().utf8_str());
419 UT_UCSChar * pData = (UT_UCSChar *) ucs_buf; // HACK: should be void *
420
421 EV_Win32Toolbar * t = (EV_Win32Toolbar *) GetWindowLongPtrW(hWnd, GWLP_USERDATA);
422 UT_ASSERT(t);
423
424 if(dataLength)
425 {
426 UINT u = GetDlgCtrlID(hWnd);
427 XAP_Toolbar_Id id = t->ItemIdFromWmCommand(u);
428
429 // If is a STYLE_NAME we should pass the internal one, not the localised
430 if (id==AP_TOOLBAR_ID_FMT_STYLE)
431 {
432 UT_sint32 iSelected;
433 int nData;
434
435 iSelected = SendMessageW(hWnd, CB_GETCURSEL, 0, 0);
436
437 // Find the proper non-localised text
438 XAP_Toolbar_ControlFactory * pFactory = t->m_pWin32App->getControlFactory();
439 EV_Toolbar_Control * pControl = pFactory->getControl(t, AP_TOOLBAR_ID_FMT_STYLE);
440 AP_Win32Toolbar_StyleCombo * pStyleC = static_cast<AP_Win32Toolbar_StyleCombo *>(pControl);
441 pStyleC->repopulate();
442
443 nData = SendMessageW(hWnd, CB_GETITEMDATA, iSelected, 0);
444
445 UT_UTF8String *utf = t->m_vecOrgStylesNames.getNthItem(nData);
446 UT_ASSERT((utf && (utf->length() < (COMBO_BUF_LEN-1))));
447 UT_UCS4_strcpy_utf8_char(ucs_buf, utf->utf8_str());
448 dataLength = UT_UCS4_strlen (ucs_buf);
449
450 DELETEP(pControl);
451 }
452
453 t->toolbarEvent(id, pData, dataLength);
454 }
455
456 SetFocus(static_cast<XAP_Win32FrameImpl*>(t->m_pWin32Frame->getFrameImpl())->getTopLevelWindow());
457 }
458 else
459 {
460 PostMessageW(hWnd, WM_KEYDOWN, VK_ESCAPE, 0);
461 }
462
463 break;
464 }
465
466
467 break;
468
469 } // swich
470 } // case command
471
472 case WM_KEYDOWN:
473 {
474 EV_Win32Toolbar * t = (EV_Win32Toolbar *) GetWindowLongPtrW(hWnd, GWLP_USERDATA);
475 UT_ASSERT(t);
476
477 switch (wParam)
478 {
479 case VK_ESCAPE:
480 {
481 // restore combo state
482 UINT u = GetDlgCtrlID(hWnd);
483 XAP_Toolbar_Id id = t->ItemIdFromWmCommand(u);
484
485 t->_refreshID(id);
486 }
487 // fall through
488
489 case VK_TAB:
490 case VK_RETURN:
491 {
492 SetFocus(static_cast<XAP_Win32FrameImpl*>(t->m_pWin32Frame->getFrameImpl())->getTopLevelWindow());
493 return 0;
494 }
495 }
496 }
497 }
498 return (CallWindowProcW(s_lpfnDefCombo, hWnd, uMessage, wParam, lParam));
499 }
500
501
502 /*****************************************************************/
503
synthesize(void)504 bool EV_Win32Toolbar::synthesize(void)
505 {
506 // create a toolbar from the info provided.
507
508 ////////////////////////////////////////////////////////////////
509 // get toolbar button appearance from the preferences
510 ////////////////////////////////////////////////////////////////
511
512 bool bIcons = true;
513 bool bText = false;
514 const gchar * szValue = NULL;
515 m_pWin32App->getPrefsValue(XAP_PREF_KEY_ToolbarAppearance,&szValue);
516 UT_return_val_if_fail((szValue) && (*szValue),false);
517
518 if (g_ascii_strcasecmp(szValue,"icon") == 0)
519 {
520 bIcons = true;
521 bText = false;
522 }
523 else if (g_ascii_strcasecmp(szValue,"text") == 0)
524 {
525 bIcons = false;
526 bText = true;
527 }
528 else if (g_ascii_strcasecmp(szValue,"both") == 0)
529 {
530 bIcons = true;
531 bText = true;
532 }
533
534 const EV_Toolbar_ActionSet * pToolbarActionSet = m_pWin32App->getToolbarActionSet();
535 UT_ASSERT(pToolbarActionSet);
536
537 UT_uint32 nrLabelItemsInLayout = m_pToolbarLayout->getLayoutItemCount();
538 UT_ASSERT(nrLabelItemsInLayout > 0);
539
540 XAP_Toolbar_ControlFactory * pFactory = m_pWin32App->getControlFactory();
541 UT_ASSERT(pFactory);
542
543 HWND hwndParent = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl())->getToolbarWindow();
544 if(hwndParent == NULL)
545 return false;
546
547 // NOTE: this toolbar will get placed later, by frame or rebar
548
549 m_hwnd = UT_CreateWindowEx(0,
550 TOOLBARCLASSNAMEW, // window class name
551 NULL, // window caption
552 WS_CHILD | WS_VISIBLE
553 | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
554 | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT
555 | ( bText && !bIcons ? TBSTYLE_LIST : 0 )
556 | TBSTYLE_CUSTOMERASE
557 | CCS_NOPARENTALIGN | CCS_NODIVIDER
558 | CCS_NORESIZE
559 , // window style
560 0, // initial x position
561 0, // initial y position
562 0, // initial x size
563 0, // initial y size
564 hwndParent, // parent window handle
565 NULL, // window menu handle
566 m_pWin32App->getInstance(), // program instance handle
567 NULL); // creation parameters
568
569
570 UT_ASSERT(m_hwnd);
571
572 // override the window procedure
573 s_lpfnDefToolBar = (WHICHPROC)GetWindowLongPtrW(m_hwnd, GWLP_WNDPROC);
574 SetWindowLongPtrW(m_hwnd, GWLP_WNDPROC, (LONG_PTR)_ToolBarWndProc);
575 SetWindowLongPtrW(m_hwnd, GWLP_USERDATA, (LONG_PTR)this);
576
577
578 SendMessageW(m_hwnd, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
579
580 // the Windows Common Control Toolbar requires that we set
581 // a bitmap size in the toolbar window **before** we actually
582 // add any of them. at this point in the code, we haven't
583 // loaded any of the bitmaps yet and thus don't know the maximum
584 // size. we could go thru the layout twice and compute the
585 // maxium before calling this, but this seems overkill since
586 // we know at compile time what all of the bitmaps are....
587 //
588 // Now bitmaps are cut down to requested size if too large - HB
589
590 const WORD MY_MAXIMUM_BITMAP_X = 24;
591 const WORD MY_MAXIMUM_BITMAP_Y = 24;
592
593 if( bIcons )
594 SendMessageW(m_hwnd, TB_SETBITMAPSIZE, 0,
595 (LPARAM) MAKELONG(MY_MAXIMUM_BITMAP_X,MY_MAXIMUM_BITMAP_Y));
596 else
597 SendMessageW(m_hwnd, TB_SETBITMAPSIZE, 0, (LPARAM) MAKELONG(0,0));
598
599 DWORD dwColor = GetSysColor(COLOR_BTNFACE);
600 UT_RGBColor backgroundColor(GetRValue(dwColor),GetGValue(dwColor),GetBValue(dwColor));
601
602 // TODO: is there any advantage to building up all the TBBUTTONs at once
603 // and then adding them en masse, instead of one at a time?
604 UINT last_id=0;
605 bool bControls = false;
606
607 for (UT_uint32 k=0; (k < nrLabelItemsInLayout); k++)
608 {
609 EV_Toolbar_LayoutItem * pLayoutItem = m_pToolbarLayout->getLayoutItem(k);
610 UT_continue_if_fail(pLayoutItem);
611
612 XAP_Toolbar_Id id = pLayoutItem->getToolbarId();
613 EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
614 UT_ASSERT(pAction);
615 EV_Toolbar_Label * pLabel = m_pToolbarLabelSet->getLabel(id);
616 UT_ASSERT(pLabel);
617
618 UINT u = WmCommandFromItemId(id);
619
620 TBBUTTON tbb;
621 memset(&tbb, 0, sizeof(tbb));
622
623 switch (pLayoutItem->getToolbarLayoutFlags())
624 {
625 case EV_TLF_Normal:
626 {
627 tbb.idCommand = u;
628 tbb.dwData = 0;
629
630 last_id = u;
631
632 bool bButton = false;
633
634 switch (pAction->getItemType())
635 {
636 //TODO: For now these are buttons which bring up a dialog, as some point,
637 //make them be able to bring up some sort of additional selector.
638 case EV_TBIT_ColorFore:
639 case EV_TBIT_ColorBack:
640 UT_DEBUGMSG(("TODO: Hey Windows needs some tender love and care and a colour selector! \n"));
641 // UT_ASSERT(UT_NOT_IMPLEMENTED);
642 UT_DEBUGMSG(("TODO: Handle the colour selector case \n"));
643 /* Fall through and make a push button */
644
645 case EV_TBIT_PushButton:
646 bButton = true;
647 tbb.fsState = TBSTATE_ENABLED;
648 tbb.fsStyle = TBSTYLE_BUTTON;
649 break;
650
651 case EV_TBIT_ToggleButton:
652 bButton = true;
653 tbb.fsState = TBSTATE_ENABLED;
654 tbb.fsStyle = TBSTYLE_CHECK;
655 break;
656
657 case EV_TBIT_GroupButton:
658 bButton = true;
659 tbb.fsState = TBSTATE_ENABLED;
660 tbb.fsStyle = TBSTYLE_CHECKGROUP;
661 break;
662
663 case EV_TBIT_ComboBox:
664 {
665 EV_Toolbar_Control * pControl = pFactory->getControl(this, id);
666 UT_ASSERT_HARMLESS(pControl);
667
668 int iWidth = 100;
669
670 if (pControl)
671 {
672 iWidth = pControl->getPixelWidth();
673 }
674
675 bControls = true;
676 tbb.fsStyle = TBSTYLE_SEP;
677 tbb.iBitmap = iWidth;
678
679 // create a matching child control
680 DWORD dwStyle = WS_CHILD | WS_BORDER | WS_VISIBLE | WS_VSCROLL |
681 CBS_HASSTRINGS | CBS_DROPDOWN;
682
683 if ((pControl) && (pControl->shouldSort()))
684 {
685 dwStyle |= CBS_SORT;
686 }
687
688 if (id==AP_TOOLBAR_ID_FMT_FONT)
689 dwStyle |= CBS_OWNERDRAWFIXED;
690
691 HWND hwndCombo = UT_CreateWindowEx ( 0L, // No extended styles.
692 L"COMBOBOX", // Class name.
693 L"", // Default text.
694 dwStyle, // Styles and defaults.
695 0, 2, iWidth, 250, // Size and position.
696 m_hwnd, // Parent window.
697 (HMENU) u, // ID.
698 m_pWin32App->getInstance(), // Current instance.
699 NULL ); // No class data.
700
701 UT_ASSERT(hwndCombo);
702
703 /*
704 * Hack to create a combobox that is readonly, but which is capable of displaying text in
705 * the edit control which differs from that in the drop-down list like GTK combos.
706 */
707 HWND hwndEdit = FindWindowExW(hwndCombo, 0, NULL, NULL);
708 if (!hwndEdit)
709 UT_DEBUGMSG(("Toolbar: Failed to get handle of combos edit controls. Not setting read-only.\n"));
710 else
711 SendMessageW(hwndEdit, EM_SETREADONLY, (WPARAM)TRUE, (LPARAM)0);
712 SendMessageW(hwndCombo, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));
713 SendMessageW(hwndCombo, CB_SETDROPPEDWIDTH,(WPARAM)pControl->getDroppedWidth(), 0);
714
715 // populate it
716 if (pControl)
717 {
718 pControl->populate();
719
720 const UT_GenericVector<const char*> * v = pControl->getContents();
721 UT_ASSERT_HARMLESS(v);
722
723 SendMessageW(hwndCombo, WM_SETREDRAW, FALSE,0);
724
725 if (v)
726 {
727 UT_uint32 items = v->getItemCount();
728 int nIndex;
729 UT_Win32LocaleString localised;
730 for (UT_uint32 k=0; k < items; k++)
731 {
732 localised.fromUTF8(v->getNthItem(k));
733 nIndex = SendMessageW(hwndCombo, CB_ADDSTRING,(WPARAM)0, (LPARAM)localised.c_str());
734 SendMessageW(hwndCombo,CB_SETITEMDATA, nIndex, k);
735 }
736 }
737
738 SendMessageW(hwndCombo, WM_SETREDRAW, TRUE,0);
739 }
740
741 // override the window procedure for the combo box
742 s_lpfnDefCombo = (WHICHPROC)GetWindowLongPtrW(hwndCombo, GWLP_WNDPROC);
743 SetWindowLongPtrW(hwndCombo, GWLP_WNDPROC, (LONG_PTR)_ComboWndProc);
744 SetWindowLongPtrW(hwndCombo, GWLP_USERDATA, (LONG_PTR)this);
745
746 // Get the handle to the tooltip window.
747 HWND hwndTT = (HWND)SendMessageW(m_hwnd, TB_GETTOOLTIPS, 0, 0);
748
749 if (hwndTT)
750 {
751 UT_Win32LocaleString str;
752 const char * szToolTip = pLabel->getToolTip();
753 if (!szToolTip || !*szToolTip)
754 {
755 szToolTip = pLabel->getStatusMsg();
756 }
757
758 str.fromUTF8 (szToolTip);
759
760 // Fill in the TOOLINFO structure.
761 TOOLINFOW ti;
762 ti.cbSize = sizeof(ti);
763 ti.uFlags = TTF_IDISHWND | TTF_CENTERTIP;
764 ti.lpszText = (wchar_t *) str.c_str();
765 ti.hwnd = m_hwnd; // TODO: should this be the frame?
766 ti.uId = (UINT_PTR)hwndCombo;
767 // Set up tooltips for the combo box.
768 SendMessageW(hwndTT, TTM_ADDTOOLW, 0, (LPARAM)(LPTOOLINFOW)&ti);
769 }
770
771 // bind this separator to its control
772 tbb.dwData = (DWORD_PTR) hwndCombo;
773
774 // for now, we never repopulate, so can just toss it
775 DELETEP(pControl);
776 }
777 break;
778
779 case EV_TBIT_EditText:
780 case EV_TBIT_DropDown:
781 case EV_TBIT_StaticLabel:
782 // TODO do these...
783 break;
784
785 case EV_TBIT_Spacer:
786 case EV_TBIT_BOGUS:
787 default:
788 UT_ASSERT_HARMLESS(0);
789 break;
790 }
791
792 if (bButton)
793 {
794 // TODO figure out who destroys hBitmap...
795 //
796 // TMN: 20 Nov 2000 - Tests display that we must hang on to the
797 // bitmap handle for this to work.
798 // Had we been allowed to use C++ I'd say
799 // std::map<std::string, HBITMAP> icons;
800 // but currently I don't know how to handle this in a clean way.
801 // Would UT_Array help?
802
803 // TODO add code to create these once per application
804 // TODO and reference them in each toolbar instance
805 // TODO rather than create them once for each window....
806
807 if (bIcons)
808 {
809 HBITMAP hBitmap;
810 UT_DebugOnly<bool> bFoundIcon =
811 XAP_Win32Toolbar_Icons::getBitmapForIcon(m_hwnd,
812 MY_MAXIMUM_BITMAP_X,
813 MY_MAXIMUM_BITMAP_Y,
814 &backgroundColor,
815 pLabel->getIconName(),
816 &hBitmap);
817 UT_ASSERT(bFoundIcon);
818
819 // TMN: I know, this is really, really bad, but it's
820 // currently the only thing we have at our disposal to
821 // release these bitmaps at program termination.
822 foo_Bitmap_container::instance().addBitmap(hBitmap);
823
824 TBADDBITMAP ab;
825 ab.hInst = 0;
826 ab.nID = (LPARAM)hBitmap;
827
828 LRESULT iAddedAt = SendMessageW(m_hwnd,TB_ADDBITMAP,1,(LPARAM)&ab);
829 UT_ASSERT(iAddedAt != -1);
830
831 tbb.iBitmap = iAddedAt;
832 }
833
834 if (bText)
835 {
836 const char * szLabel = pLabel->getToolbarLabel();
837 // As long as translators don't cut the text short,
838 // we need to autosize just to squize anything insize 1280 :)
839 tbb.fsStyle |= TBSTYLE_AUTOSIZE;
840 tbb.iString = SendMessageW(m_hwnd, TB_ADDSTRING, (WPARAM) 0, (LPARAM) (LPSTR) szLabel);
841 }
842
843 if (pAction->getItemType() == EV_TBIT_ColorFore || pAction->getItemType() == EV_TBIT_ColorBack)
844 {
845 tbb.fsStyle |=TBSTYLE_DROPDOWN;
846
847 //tbb.fsStyle |=BTNS_WHOLEDROPDOWN;
848
849 DWORD dwStyle = SendMessageW(m_hwnd, TB_GETEXTENDEDSTYLE, (WPARAM) 0, (LPARAM) 0);
850 dwStyle |= TBSTYLE_EX_DRAWDDARROWS;
851 SendMessageW(m_hwnd, TB_SETEXTENDEDSTYLE, (WPARAM) 0, (LPARAM) dwStyle);
852 }
853
854 }
855 }
856 break;
857
858 case EV_TLF_Spacer:
859 tbb.fsState = TBSTATE_ENABLED;
860 tbb.fsStyle = TBSTYLE_SEP;
861 break;
862
863 default:
864 UT_ASSERT_HARMLESS(0);
865 }
866
867 // add this button to the bar
868 SendMessageW(m_hwnd, TB_ADDBUTTONS, (WPARAM) 1, (LPARAM) (LPTBBUTTON) &tbb);
869 }
870
871 // figure out bar dimensions now that buttons are all there
872 SendMessageW(m_hwnd, TB_AUTOSIZE, 0, 0);
873
874 if (bControls)
875 {
876 // move each control on top of its associated separator
877 for (UT_uint32 k=0; (k < nrLabelItemsInLayout); k++)
878 {
879 EV_Toolbar_LayoutItem * pLayoutItem = m_pToolbarLayout->getLayoutItem(k);
880 UT_continue_if_fail(pLayoutItem);
881
882 XAP_Toolbar_Id id = pLayoutItem->getToolbarId();
883 EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
884 UT_continue_if_fail(pAction);
885
886 RECT r;
887 HWND hwndCtrl;
888 int nHeight, nSep;
889
890 switch (pAction->getItemType())
891 {
892 case EV_TBIT_ComboBox:
893 hwndCtrl = _getControlWindow(id);
894 UT_ASSERT(hwndCtrl);
895 GetWindowRect(hwndCtrl, &r);
896 nHeight = r.bottom - r.top;
897
898 SendMessageW(m_hwnd, TB_GETITEMRECT, (WPARAM) k, (LPARAM)(LPRECT) &r);
899
900 nSep = (r.bottom - r.top - nHeight)/2;
901 if (nSep < 0)
902 nSep = 0;
903
904 MoveWindow(hwndCtrl, r.left, r.top + nSep, r.right - r.left, nHeight, TRUE);
905
906 break;
907
908 case EV_TBIT_EditText:
909 case EV_TBIT_DropDown:
910 case EV_TBIT_StaticLabel:
911 // TODO do these...
912 break;
913
914 default:
915 break;
916 }
917 }
918 }
919
920 UT_ASSERT(last_id > 0);
921
922 _addToRebar(); // add this bar to the rebar
923
924 // I think that this is true due to the WS_VISIBLE flag
925 // sent to CreateWindowEx
926 m_bVisible = true;
927
928 return true;
929 }
930
getWindow(void) const931 HWND EV_Win32Toolbar::getWindow(void) const
932 {
933 return m_hwnd;
934 }
935
_getControlWindow(XAP_Toolbar_Id id)936 HWND EV_Win32Toolbar::_getControlWindow(XAP_Toolbar_Id id)
937 {
938 TBBUTTON tbb;
939 HWND hwndCtrl;
940 UINT u = WmCommandFromItemId(id);
941
942 UT_uint32 k = SendMessageW(m_hwnd, TB_COMMANDTOINDEX, (WPARAM) u, 0);
943 SendMessageW(m_hwnd, TB_GETBUTTON, (WPARAM) k, (LPARAM)(LPTBBUTTON) &tbb);
944 UT_ASSERT(tbb.idCommand == (int) u);
945 UT_ASSERT(tbb.fsStyle & TBSTYLE_SEP);
946
947 hwndCtrl = (HWND) tbb.dwData;
948
949 return hwndCtrl;
950 }
951
_releaseListener(void)952 void EV_Win32Toolbar::_releaseListener(void)
953 {
954 if (!m_pViewListener)
955 return;
956 DELETEP(m_pViewListener);
957 m_pViewListener = 0;
958 m_lid = 0;
959 }
960
bindListenerToView(AV_View * pView)961 bool EV_Win32Toolbar::bindListenerToView(AV_View * pView)
962 {
963 if(m_hwnd == NULL)
964 return false;
965
966 _releaseListener();
967
968 m_pViewListener = new EV_Win32Toolbar_ViewListener(this,pView);
969 UT_ASSERT(m_pViewListener);
970
971 UT_DebugOnly<bool> bResult = pView->addListener(static_cast<AV_Listener *>(m_pViewListener),&m_lid);
972 UT_ASSERT(bResult);
973
974 if(pView->isDocumentPresent())
975 {
976 refreshToolbar(pView, AV_CHG_ALL);
977 }
978
979 return true;
980 }
981
refreshToolbar(AV_View * pView,AV_ChangeMask mask)982 bool EV_Win32Toolbar::refreshToolbar(AV_View * pView, AV_ChangeMask mask)
983 {
984 if(m_hwnd == NULL)
985 return false;
986
987 // make the toolbar reflect the current state of the document
988 // at the current insertion point or selection.
989
990 const EV_Toolbar_ActionSet * pToolbarActionSet = m_pWin32App->getToolbarActionSet();
991 UT_ASSERT(pToolbarActionSet);
992
993 UT_uint32 nrLabelItemsInLayout = m_pToolbarLayout->getLayoutItemCount();
994 for (UT_uint32 k=0; (k < nrLabelItemsInLayout); k++)
995 {
996 EV_Toolbar_LayoutItem * pLayoutItem = m_pToolbarLayout->getLayoutItem(k);
997 UT_continue_if_fail(pLayoutItem);
998
999 XAP_Toolbar_Id id = pLayoutItem->getToolbarId();
1000 EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
1001 UT_continue_if_fail(pAction);
1002
1003 AV_ChangeMask maskOfInterest = pAction->getChangeMaskOfInterest();
1004 if ((maskOfInterest & mask) == 0) // if this item doesn't care about
1005 continue; // changes of this type, skip it...
1006
1007 switch (pLayoutItem->getToolbarLayoutFlags())
1008 {
1009 case EV_TLF_Normal:
1010 _refreshItem(pView, pAction, id);
1011 break;
1012
1013 case EV_TLF_Spacer:
1014 break;
1015
1016 default:
1017 UT_ASSERT_HARMLESS(0);
1018 break;
1019 }
1020 }
1021
1022 return true;
1023 }
1024
_refreshID(XAP_Toolbar_Id id)1025 bool EV_Win32Toolbar::_refreshID(XAP_Toolbar_Id id)
1026 {
1027 const EV_Toolbar_ActionSet * pToolbarActionSet = m_pWin32App->getToolbarActionSet();
1028 UT_return_val_if_fail(pToolbarActionSet,false);
1029
1030 EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
1031 UT_ASSERT(pAction);
1032
1033 AV_View * pView = m_pWin32Frame->getCurrentView();
1034 UT_ASSERT(pView);
1035
1036 return _refreshItem(pView, pAction, id);
1037 }
1038
_refreshItem(AV_View * pView,const EV_Toolbar_Action * pAction,XAP_Toolbar_Id id)1039 bool EV_Win32Toolbar::_refreshItem(AV_View * pView, const EV_Toolbar_Action * pAction, XAP_Toolbar_Id id)
1040 {
1041 const char * szState = 0;
1042 EV_Toolbar_ItemState tis = pAction->getToolbarItemState(pView,&szState);
1043
1044 UINT u = WmCommandFromItemId(id);
1045
1046 switch (pAction->getItemType())
1047 {
1048 // These two are unhandled and for the moment drop down to PushButton
1049 case EV_TBIT_ColorFore:
1050 case EV_TBIT_ColorBack:
1051
1052 case EV_TBIT_PushButton:
1053 {
1054 bool bGrayed = EV_TIS_ShouldBeGray(tis);
1055
1056 SendMessageW(m_hwnd, TB_ENABLEBUTTON, u, (!bGrayed ? 1 : 0)) ;
1057
1058 //UT_DEBUGMSG(("refreshToolbar: PushButton [%s] is %s\n",
1059 // m_pToolbarLabelSet->getLabel(id)->getToolbarLabel(),
1060 // ((bGrayed) ? "disabled" : "enabled")));
1061 }
1062 break;
1063
1064 case EV_TBIT_ToggleButton:
1065 case EV_TBIT_GroupButton:
1066 {
1067 bool bGrayed = EV_TIS_ShouldBeGray(tis);
1068 bool bToggled = EV_TIS_ShouldBeToggled(tis);
1069
1070 SendMessageW(m_hwnd, TB_ENABLEBUTTON, u, (!bGrayed ? 1 : 0));
1071 SendMessageW(m_hwnd, TB_CHECKBUTTON, u, (bToggled ? 1 : 0));
1072
1073 //UT_DEBUGMSG(("refreshToolbar: ToggleButton [%s] is %s and %s\n",
1074 // m_pToolbarLabelSet->getLabel(id)->getToolbarLabel(),
1075 // ((bGrayed) ? "disabled" : "enabled"),
1076 // ((bToggled) ? "pressed" : "not pressed")));
1077 }
1078 break;
1079
1080 case EV_TBIT_ComboBox:
1081 {
1082 //bool bGrayed = EV_TIS_ShouldBeGray(tis);
1083 //bool bString = EV_TIS_ShouldUseString(tis);
1084 HWND hwndCombo = _getControlWindow(id);
1085 UT_return_val_if_fail(hwndCombo, true);
1086 std::string utf8;
1087 UT_String str;
1088
1089 // NOTE: we always update the control even if !szState
1090 if (!szState)
1091 {
1092 int idx = SendMessageW(hwndCombo, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)szState);
1093 if (idx==CB_ERR)
1094 SetWindowTextW(hwndCombo, L"");
1095 break;
1096 }
1097
1098 // Find the proper non-localised text
1099 UT_Win32LocaleString localised;
1100 if (id==AP_TOOLBAR_ID_FMT_STYLE)
1101 {
1102 pt_PieceTable::s_getLocalisedStyleName(szState, utf8);
1103 localised.fromUTF8 (utf8.c_str());
1104 }
1105 else
1106 localised.fromUTF8 (szState);
1107
1108 int idx = SendMessageW(hwndCombo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)localised.c_str());
1109 if (idx!=CB_ERR)
1110 SendMessageW(hwndCombo, CB_SETCURSEL, idx, 0);
1111 /*
1112 * If the string didn't exist within the combos list, we handle things differently for
1113 * different combos.
1114 */
1115 if (idx==CB_ERR)
1116 {
1117 const XAP_StringSet * pSS;
1118
1119 switch (id)
1120 {
1121 /*
1122 * In the case of the font and font size combo, this means that the document contains a font not
1123 * installed on the system. Add it to the edit control, as is the case with the unix version.
1124 */
1125 case AP_TOOLBAR_ID_FMT_SIZE:
1126 case AP_TOOLBAR_ID_FMT_FONT:
1127 idx = SendMessageW(hwndCombo, WM_SETTEXT, (WPARAM)-1, (LPARAM)localised.c_str());
1128 if (idx == CB_ERR)
1129 {
1130 UT_DEBUGMSG(("refreshToolbar: Failed to set text for font combo.\n"));
1131 }
1132 break;
1133 /*
1134 * If this is the zoom combo, select the "Other..." string.
1135 */
1136 case AP_TOOLBAR_ID_ZOOM:
1137 pSS = XAP_App::getApp()->getStringSet();
1138 localised.fromUTF8 (pSS->getValue(XAP_STRING_ID_TB_Zoom_Percent));
1139 idx = SendMessageW(hwndCombo, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)localised.c_str());
1140 break;
1141
1142 case AP_TOOLBAR_ID_FMT_STYLE:
1143 UT_DEBUGMSG(("refreshToolbar: Unknown string selected in style combo.\n"));
1144 break;
1145 default:
1146 UT_DEBUGMSG(("refreshToolbar: Unknown string selected in unknown combo.\n"));
1147 break;
1148 }
1149 }
1150
1151 //UT_DEBUGMSG(("refreshToolbar: ComboBox [%s] is %s and %s\n",
1152 // m_pToolbarLabelSet->getLabel(id)->getToolbarLabel(),
1153 // ((bGrayed) ? "disabled" : "enabled"),
1154 // ((bString) ? szState : "no state")));
1155 }
1156 break;
1157
1158 case EV_TBIT_EditText:
1159 case EV_TBIT_DropDown:
1160 case EV_TBIT_StaticLabel:
1161 case EV_TBIT_Spacer:
1162 // TODO do these later...
1163 break;
1164
1165
1166 case EV_TBIT_BOGUS:
1167 default:
1168 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1169 break;
1170 }
1171
1172 return true;
1173 }
1174
getToolTip(LPARAM lParam)1175 bool EV_Win32Toolbar::getToolTip(LPARAM lParam)
1176 {
1177 UT_ASSERT(lParam);
1178 LPTOOLTIPTEXTW lpttt = (LPTOOLTIPTEXTW) lParam;
1179
1180 // who's asking?
1181 UINT idButton = lpttt->hdr.idFrom;
1182 XAP_Toolbar_Id id = ItemIdFromWmCommand(idButton);
1183
1184 EV_Toolbar_Label * pLabel = m_pToolbarLabelSet->getLabel(id);
1185 if (!pLabel)
1186 return false;
1187
1188 // ok, gotcha
1189 const char * szToolTip = pLabel->getToolTip();
1190 if (!szToolTip || !*szToolTip)
1191 {
1192 szToolTip = pLabel->getStatusMsg();
1193 }
1194
1195 if (!szToolTip || !*szToolTip)
1196 {
1197 szToolTip = pLabel->getToolbarLabel();
1198 }
1199
1200 if (szToolTip && *szToolTip)
1201 {
1202 UT_Win32LocaleString str;
1203 str.fromUTF8 (szToolTip);
1204 wcsncpy(lpttt->lpszText, str.c_str(),80);
1205 }
1206 else
1207 {
1208 lpttt->lpszText[0] = '\0';
1209 }
1210 lpttt->hinst=NULL;
1211
1212 return true;
1213 }
1214
1215
show(void)1216 void EV_Win32Toolbar::show(void)
1217 {
1218 UT_return_if_fail(m_pWin32Frame);
1219 UT_DebugOnly<HWND> hRebar = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl())->getToolbarWindow();
1220 UT_ASSERT(hRebar);
1221 UT_DebugOnly<int> iBand = _getBandForHwnd(m_hwnd);
1222 UT_ASSERT(iBand < 0); // It can't already be displayed!
1223 _addToRebar();
1224
1225 m_bVisible = true;
1226 }
1227
hide(void)1228 void EV_Win32Toolbar::hide(void)
1229 {
1230 UT_return_if_fail(m_pWin32Frame);
1231 HWND hRebar = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl())->getToolbarWindow();
1232 UT_ASSERT(hRebar);
1233 const int iBand = _getBandForHwnd(m_hwnd);
1234 if (iBand >= 0)
1235 {
1236 SendMessageW(hRebar, RB_DELETEBAND, (WPARAM)iBand, 0);
1237 m_bVisible = false;
1238 }
1239 }
1240
1241 //
1242 // Returns the index of hToolbar in the rebar hRebar.
1243 // Returns -1 on error or if the toolbar wasn't recognized as a
1244 // child of the specified rebar control.
1245 //
_getBandForHwnd(HWND hToolbar) const1246 int EV_Win32Toolbar::_getBandForHwnd(HWND hToolbar) const
1247 {
1248 HWND hRebar = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl())->getToolbarWindow();
1249
1250 // If we ever get more than 20 toolbars I don't wanna be around.
1251 REBARBANDINFOW rbi;
1252 memset(&rbi, 0, sizeof(rbi));
1253 rbi.cbSize = sizeof(rbi);
1254 rbi.fMask = RBBIM_CHILD;
1255 for (int i = 0; i < 20; ++i)
1256 {
1257 if (!SendMessageW(hRebar, RB_GETBANDINFO, (WPARAM)i, (LPARAM)&rbi))
1258 {
1259 continue;
1260 }
1261 if (hToolbar == rbi.hwndChild)
1262 {
1263 return i;
1264 }
1265 }
1266 return -1;
1267 }
1268
_addToRebar()1269 void EV_Win32Toolbar::_addToRebar()
1270 {
1271 // Get the height of the toolbar.
1272 DWORD dwBtnSize = SendMessageW(m_hwnd, TB_GETBUTTONSIZE, 0,0);
1273
1274 RECT rc;
1275 GetWindowRect(m_hwnd, &rc);
1276 // UINT iWidth = rc.right + 13;
1277 UINT iWidth = rc.right - rc.left + 13;
1278
1279 // add this bar to the rebar
1280 REBARBANDINFOW rbbi;
1281 memset(&rbbi, 0, sizeof(rbbi));
1282 // Initialize REBARBANDINFO
1283 rbbi.cbSize = sizeof(REBARBANDINFOW);
1284 rbbi.fMask = RBBIM_COLORS | // clrFore and clrBack are valid
1285 RBBIM_CHILD | // hwndChild is valid
1286 RBBIM_CHILDSIZE | // cxMinChild and cyMinChild are valid
1287 RBBIM_SIZE | // cx is valid
1288 RBBIM_STYLE; // fStyle is valid
1289 rbbi.clrFore = GetSysColor(COLOR_BTNTEXT);
1290 rbbi.clrBack = GetSysColor(COLOR_BTNFACE);
1291 // NOT using RBBS_CHILDEDGE for fStyle gives us a slimmer look,
1292 // better with the flat button style.
1293 rbbi.fStyle = RBBS_NOVERT | // do not display in vertical orientation
1294 RBBS_BREAK;
1295 rbbi.hwndChild = m_hwnd;
1296 rbbi.cxMinChild = LOWORD(dwBtnSize);
1297 rbbi.cyMinChild = HIWORD(dwBtnSize);
1298 rbbi.cx = iWidth;
1299
1300 HWND hRebar = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl())->getToolbarWindow();
1301 // Add it at the the end
1302 SendMessageW(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi);
1303 }
1304
1305
getFrame(void)1306 XAP_Frame * EV_Win32Toolbar::getFrame(void)
1307 {
1308 return m_pWin32Frame;
1309 }
1310
1311
1312 /*!
1313 * This method examines the current document and repopulates the Styles
1314 * Combo box with what is in the document. It returns false if no styles
1315 * combo box was found. True if it all worked.
1316 */
repopulateStyles(void)1317 bool EV_Win32Toolbar::repopulateStyles(void)
1318 {
1319 //
1320 // First off find the Styles combobox in a toolbar somewhere
1321 //
1322 UT_uint32 count = m_pToolbarLayout->getLayoutItemCount();
1323 UT_uint32 i =0;
1324 EV_Toolbar_LayoutItem * pLayoutItem = NULL;
1325 XAP_Toolbar_Id id;
1326 for(i=0; i < count; i++)
1327 {
1328 pLayoutItem = m_pToolbarLayout->getLayoutItem(i);
1329 id = pLayoutItem->getToolbarId();
1330 // wd = (_wd *) getNthItem(i);
1331 if(id == AP_TOOLBAR_ID_FMT_STYLE)
1332 break;
1333 }
1334 if(i>=count)
1335 return false;
1336
1337
1338
1339 //
1340 // GOT IT!
1341 //
1342 // UT_ASSERT(wd->m_id == AP_TOOLBAR_ID_FMT_STYLE);
1343 XAP_Toolbar_ControlFactory * pFactory = m_pWin32App->getControlFactory();
1344 UT_return_val_if_fail(pFactory,false);
1345 EV_Toolbar_Control * pControl = pFactory->getControl(this, id);
1346 AP_Win32Toolbar_StyleCombo * pStyleC = static_cast<AP_Win32Toolbar_StyleCombo *>(pControl);
1347 pStyleC->repopulate();
1348
1349
1350 HWND hwndCombo = _getControlWindow(id);
1351 UT_ASSERT(hwndCombo);
1352 // GtkCombo * item = GTK_COMBO(wd->m_widget);
1353 //
1354 // Now the combo box has to be refilled from this
1355 //
1356 const UT_GenericVector<const char*> * v = pControl->getContents();
1357 UT_return_val_if_fail(v,false);
1358
1359 //
1360 // Now we must remove and delete the old data so we add the new
1361 // list of styles to the combo box.
1362 //
1363 // Try this....
1364 SendMessageW(hwndCombo, WM_SETREDRAW, FALSE, 0);
1365 SendMessageW(hwndCombo, CB_RESETCONTENT, 0 , 0);
1366
1367 SendMessageW(hwndCombo, CB_SETDROPPEDWIDTH,
1368 (WPARAM)pStyleC->getDroppedWidth(), 0);
1369
1370 //
1371 // GtkList * oldlist = GTK_LIST(item->list);
1372 // gtk_list_clear_items(oldlist,0,-1);
1373 //
1374 // Now make a new one.
1375 //
1376 int nItem;
1377 std::string utf8;
1378 UT_String str;
1379
1380 for (UT_sint32 c=0; c < m_vecOrgStylesNames.getItemCount(); c++)
1381 delete m_vecOrgStylesNames.getNthItem(c);
1382
1383 m_vecOrgStylesNames.clear();
1384
1385
1386 for (UT_sint32 k=0; k < v->getItemCount(); k++)
1387 {
1388 const char* sz = (char *)v->getNthItem(k);
1389 UT_Win32LocaleString localised;
1390
1391 pt_PieceTable::s_getLocalisedStyleName(sz, utf8);
1392 localised.fromUTF8 (utf8.c_str());
1393
1394 nItem = SendMessageW(hwndCombo, CB_ADDSTRING,(WPARAM)0, (LPARAM)localised.c_str());
1395 m_vecOrgStylesNames.addItem (new UT_UTF8String ((char *)v->getNthItem(k)));
1396 SendMessageW(hwndCombo, CB_SETITEMDATA,(WPARAM)nItem, (LPARAM)m_vecOrgStylesNames.getItemCount()-1);
1397 }
1398 //
1399 // Don't need this anymore and we don't like memory leaks in abi
1400 //
1401 SendMessageW(hwndCombo, WM_SETREDRAW, TRUE, 0);
1402 InvalidateRect (hwndCombo, NULL, true);
1403 delete pStyleC;
1404 //
1405 // I think we've finished!
1406 //
1407 return true;
1408 }
1409
1410 /*
1411 This method is called when the user clicks on the arrow next to the
1412 foreground and background colour seletion buttons on the toolbar
1413 */
onDropArrow(UINT cmd)1414 void EV_Win32Toolbar::onDropArrow(UINT cmd)
1415 {
1416 AV_View * pView = m_pWin32Frame->getCurrentView();
1417 XAP_Frame * pFrame = (XAP_Frame *) pView->getParentData();
1418 UT_return_if_fail(pFrame);
1419
1420 UT_UCS4String ucs4color;
1421 int id = ItemIdFromWmCommand(cmd);
1422
1423 pFrame->raise();
1424
1425 XAP_DialogFactory * pDialogFactory
1426 = (XAP_DialogFactory *)(pFrame->getDialogFactory());
1427
1428 AP_Dialog_Background * pDialog
1429 = (AP_Dialog_Background *)(pDialogFactory->requestDialog(AP_DIALOG_ID_BACKGROUND));
1430 UT_ASSERT_HARMLESS(pDialog);
1431 if (pDialog)
1432 {
1433 //
1434 // Get Current color
1435 //
1436
1437 const EV_Toolbar_ActionSet * pToolbarActionSet = m_pWin32App->getToolbarActionSet();
1438 UT_return_if_fail(pToolbarActionSet);
1439
1440 const EV_Toolbar_Action * pAction = pToolbarActionSet->getAction(id);
1441 if (!pAction) return;
1442
1443
1444 XAP_Win32FrameImpl* fimpl = static_cast<XAP_Win32FrameImpl*>(m_pWin32Frame->getFrameImpl());
1445
1446 if (!fimpl->m_sColorBack.empty() && pAction->getItemType() == EV_TBIT_ColorBack)
1447 pDialog->setColor(fimpl->m_sColorBack.utf8_str());
1448
1449 if (!fimpl->m_sColorFore.empty() && pAction->getItemType() == EV_TBIT_ColorFore)
1450 pDialog->setColor(fimpl->m_sColorFore.utf8_str());
1451
1452 pDialog->runModal (pFrame);
1453
1454 AP_Dialog_Background::tAnswer ans = pDialog->getAnswer();
1455 bool bOK = (ans == AP_Dialog_Background::a_OK);
1456
1457 if (bOK)
1458 {
1459 UT_UTF8String strColor;
1460 strColor = (reinterpret_cast<const char *>(pDialog->getColor()));
1461
1462 if (pAction->getItemType() == EV_TBIT_ColorBack)
1463 fimpl->m_sColorBack = strColor;
1464
1465 if (pAction->getItemType() == EV_TBIT_ColorFore)
1466 fimpl->m_sColorFore = strColor;
1467
1468 toolbarEvent(id, NULL, 0);
1469 }
1470
1471 pDialogFactory->releaseDialog(pDialog);
1472 }
1473 }
1474
1475