PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/os2/button.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 435 lines | 270 code | 63 blank | 102 comment | 33 complexity | f1be472a50c50e0b538c517e34bba30c MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/os2/button.cpp
  3. // Purpose: wxButton
  4. // Author: David Webster
  5. // Modified by:
  6. // Created: 10/13/99
  7. // RCS-ID: $Id$
  8. // Copyright: (c) David Webster
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. // For compilers that support precompilation, includes "wx.h".
  12. #include "wx/wxprec.h"
  13. #include "wx/button.h"
  14. #ifndef WX_PRECOMP
  15. #include "wx/app.h"
  16. #include "wx/brush.h"
  17. #include "wx/panel.h"
  18. #include "wx/bmpbuttn.h"
  19. #include "wx/settings.h"
  20. #include "wx/dcscreen.h"
  21. #include "wx/scrolwin.h"
  22. #include "wx/toplevel.h"
  23. #endif
  24. #include "wx/stockitem.h"
  25. #include "wx/os2/private.h"
  26. #define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10)
  27. //
  28. // Should be at the very least less than winDEFAULT_BUTTON_MARGIN
  29. //
  30. #define FOCUS_MARGIN 3
  31. #ifndef BST_CHECKED
  32. #define BST_CHECKED 0x0001
  33. #endif
  34. // Button
  35. bool wxButton::Create( wxWindow* pParent,
  36. wxWindowID vId,
  37. const wxString& rsLbl,
  38. const wxPoint& rPos,
  39. const wxSize& rSize,
  40. long lStyle,
  41. const wxValidator& rValidator,
  42. const wxString& rsName)
  43. {
  44. wxString rsLabel(rsLbl);
  45. if (rsLabel.empty() && wxIsStockID(vId))
  46. rsLabel = wxGetStockLabel(vId);
  47. wxString sLabel = ::wxPMTextToLabel(rsLabel);
  48. SetName(rsName);
  49. #if wxUSE_VALIDATORS
  50. SetValidator(rValidator);
  51. #endif
  52. m_windowStyle = lStyle;
  53. pParent->AddChild((wxButton *)this);
  54. if (vId == -1)
  55. m_windowId = NewControlId();
  56. else
  57. m_windowId = vId;
  58. lStyle = WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON;
  59. //
  60. // OS/2 PM does not have Right/Left/Top/Bottom styles.
  61. // We will have to define an additional style when we implement notebooks
  62. // for a notebook page button
  63. //
  64. if (m_windowStyle & wxCLIP_SIBLINGS )
  65. lStyle |= WS_CLIPSIBLINGS;
  66. m_hWnd = (WXHWND)::WinCreateWindow( GetHwndOf(pParent) // Parent handle
  67. ,WC_BUTTON // A Button class window
  68. ,sLabel.c_str() // Button text
  69. ,lStyle // Button style
  70. ,0, 0, 0, 0 // Location and size
  71. ,GetHwndOf(pParent) // Owner handle
  72. ,HWND_TOP // Top of Z-Order
  73. ,vId // Identifier
  74. ,NULL // No control data
  75. ,NULL // No Presentation parameters
  76. );
  77. if (m_hWnd == 0)
  78. {
  79. return false;
  80. }
  81. //
  82. // Subclass again for purposes of dialog editing mode
  83. //
  84. SubclassWin(m_hWnd);
  85. wxFont* pButtonFont = new wxFont( 8
  86. ,wxSWISS
  87. ,wxNORMAL
  88. ,wxNORMAL
  89. );
  90. SetFont(*pButtonFont);
  91. SetXComp(0);
  92. SetYComp(0);
  93. SetSize( rPos.x
  94. ,rPos.y
  95. ,rSize.x
  96. ,rSize.y
  97. );
  98. delete pButtonFont;
  99. return true;
  100. } // end of wxButton::Create
  101. wxButton::~wxButton()
  102. {
  103. wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
  104. if (tlw)
  105. {
  106. if (tlw->GetDefaultItem() == this)
  107. {
  108. //
  109. // Don't leave the panel with invalid default item
  110. //
  111. tlw->SetDefaultItem(NULL);
  112. }
  113. }
  114. } // end of wxButton::~wxButton
  115. // ----------------------------------------------------------------------------
  116. // size management including autosizing
  117. // ----------------------------------------------------------------------------
  118. wxSize wxButton::DoGetBestSize() const
  119. {
  120. wxString rsLabel = wxGetWindowText(GetHWND());
  121. int nWidthButton;
  122. int nWidthChar;
  123. int nHeightChar;
  124. wxFont vFont = (wxFont)GetFont();
  125. GetTextExtent( rsLabel
  126. ,&nWidthButton
  127. ,NULL
  128. );
  129. wxGetCharSize( GetHWND()
  130. ,&nWidthChar
  131. ,&nHeightChar
  132. ,&vFont
  133. );
  134. //
  135. // Add a margin - the button is wider than just its label
  136. //
  137. nWidthButton += 3 * nWidthChar;
  138. //
  139. // The button height is proportional to the height of the font used
  140. //
  141. int nHeightButton = BUTTON_HEIGHT_FROM_CHAR_HEIGHT(nHeightChar);
  142. //
  143. // Need a little extra to make it look right
  144. //
  145. nHeightButton += (int)(nHeightChar/1.5);
  146. if (!HasFlag(wxBU_EXACTFIT))
  147. {
  148. wxSize vSize = GetDefaultSize();
  149. if (nWidthButton > vSize.x)
  150. vSize.x = nWidthButton;
  151. if (nHeightButton > vSize.y)
  152. vSize.y = nHeightButton;
  153. return vSize;
  154. }
  155. return wxSize( nWidthButton
  156. ,nHeightButton
  157. );
  158. } // end of wxButton::DoGetBestSize
  159. /* static */
  160. wxSize wxButton::GetDefaultSize()
  161. {
  162. static wxSize vSizeBtn;
  163. if (vSizeBtn.x == 0)
  164. {
  165. wxScreenDC vDc;
  166. vDc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
  167. //
  168. // The size of a standard button in the dialog units is 50x14,
  169. // translate this to pixels
  170. // NB1: the multipliers come from the Windows convention
  171. // NB2: the extra +1/+2 were needed to get the size be the same as the
  172. // size of the buttons in the standard dialog - I don't know how
  173. // this happens, but on my system this size is 75x23 in pixels and
  174. // 23*8 isn't even divisible by 14... Would be nice to understand
  175. // why these constants are needed though!
  176. vSizeBtn.x = (50 * (vDc.GetCharWidth() + 1))/4;
  177. vSizeBtn.y = ((14 * vDc.GetCharHeight()) + 2)/8;
  178. }
  179. return vSizeBtn;
  180. } // end of wxButton::GetDefaultSize
  181. void wxButton::Command (
  182. wxCommandEvent& rEvent
  183. )
  184. {
  185. ProcessCommand (rEvent);
  186. } // end of wxButton::Command
  187. // ----------------------------------------------------------------------------
  188. // helpers
  189. // ----------------------------------------------------------------------------
  190. bool wxButton::SendClickEvent()
  191. {
  192. wxCommandEvent vEvent( wxEVT_COMMAND_BUTTON_CLICKED
  193. ,GetId()
  194. );
  195. vEvent.SetEventObject(this);
  196. return ProcessCommand(vEvent);
  197. } // end of wxButton::SendClickEvent
  198. wxWindow *wxButton::SetDefault()
  199. {
  200. //
  201. // Set this one as the default button both for wxWidgets and Windows
  202. //
  203. wxWindow* pWinOldDefault = wxButtonBase::SetDefault();
  204. SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton), false);
  205. SetDefaultStyle( this, true );
  206. return pWinOldDefault;
  207. } // end of wxButton::SetDefault
  208. void wxButton::SetTmpDefault()
  209. {
  210. wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
  211. wxCHECK_RET( tlw, wxT("button without top level window?") );
  212. wxWindow* pWinOldDefault = tlw->GetDefaultItem();
  213. tlw->SetTmpDefaultItem(this);
  214. SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton), false);
  215. SetDefaultStyle( this, true );
  216. } // end of wxButton::SetTmpDefault
  217. void wxButton::UnsetTmpDefault()
  218. {
  219. wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
  220. wxCHECK_RET( tlw, wxT("button without top level window?") );
  221. tlw->SetTmpDefaultItem(NULL);
  222. wxWindow* pWinOldDefault = tlw->GetDefaultItem();
  223. SetDefaultStyle( this, false );
  224. SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton), true );
  225. } // end of wxButton::UnsetTmpDefault
  226. void wxButton::SetDefaultStyle(
  227. wxButton* pBtn
  228. , bool bOn
  229. )
  230. {
  231. long lStyle;
  232. //
  233. // We may be called with NULL pointer -- simpler to do the check here than
  234. // in the caller which does wxDynamicCast()
  235. //
  236. if (!pBtn)
  237. return;
  238. //
  239. // First, let DefDlgProc() know about the new default button
  240. //
  241. if (bOn)
  242. {
  243. if (!wxTheApp->IsActive())
  244. return;
  245. //
  246. // In OS/2 the dialog/panel doesn't really know it has a default
  247. // button, the default button simply has that style. We'll just
  248. // simulate by setting focus to it
  249. //
  250. pBtn->SetFocus();
  251. }
  252. lStyle = ::WinQueryWindowULong(GetHwndOf(pBtn), QWL_STYLE);
  253. if (!(lStyle & BS_DEFAULT) == bOn)
  254. {
  255. if ((lStyle & BS_USERBUTTON) != BS_USERBUTTON)
  256. {
  257. if (bOn)
  258. lStyle |= BS_DEFAULT;
  259. else
  260. lStyle &= ~BS_DEFAULT;
  261. ::WinSetWindowULong(GetHwndOf(pBtn), QWL_STYLE, lStyle);
  262. }
  263. else
  264. {
  265. //
  266. // Redraw the button - it will notice itself that it's not the
  267. // default one any longer
  268. //
  269. pBtn->Refresh();
  270. }
  271. }
  272. } // end of wxButton::UpdateDefaultStyle
  273. // ----------------------------------------------------------------------------
  274. // event/message handlers
  275. // ----------------------------------------------------------------------------
  276. bool wxButton::OS2Command(WXUINT uParam, WXWORD WXUNUSED(wId))
  277. {
  278. bool bProcessed = false;
  279. switch (uParam)
  280. {
  281. case BN_CLICKED: // normal buttons send this
  282. case BN_DBLCLICKED: // owner-drawn ones also send this
  283. bProcessed = SendClickEvent();
  284. break;
  285. }
  286. return bProcessed;
  287. } // end of wxButton::OS2Command
  288. WXHBRUSH wxButton::OnCtlColor( WXHDC WXUNUSED(pDC),
  289. WXHWND WXUNUSED(pWnd),
  290. WXUINT WXUNUSED(nCtlColor),
  291. WXUINT WXUNUSED(uMessage),
  292. WXWPARAM WXUNUSED(wParam),
  293. WXLPARAM WXUNUSED(lParam) )
  294. {
  295. wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( GetBackgroundColour()
  296. ,wxSOLID
  297. );
  298. return (WXHBRUSH)pBackgroundBrush->GetResourceHandle();
  299. } // end of wxButton::OnCtlColor
  300. void wxButton::MakeOwnerDrawn()
  301. {
  302. long lStyle = 0L;
  303. lStyle = ::WinQueryWindowULong(GetHwnd(), QWL_STYLE);
  304. if ((lStyle & BS_USERBUTTON) != BS_USERBUTTON)
  305. {
  306. //
  307. // Make it so
  308. //
  309. lStyle |= BS_USERBUTTON;
  310. ::WinSetWindowULong(GetHwnd(), QWL_STYLE, lStyle);
  311. }
  312. } // end of wxButton::MakeOwnerDrawn
  313. WXDWORD wxButton::OS2GetStyle(
  314. long lStyle
  315. , WXDWORD* pdwExstyle
  316. ) const
  317. {
  318. //
  319. // Buttons never have an external border, they draw their own one
  320. //
  321. WXDWORD dwStyle = wxControl::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
  322. ,pdwExstyle
  323. );
  324. //
  325. // We must use WS_CLIPSIBLINGS with the buttons or they would draw over
  326. // each other in any resizable dialog which has more than one button in
  327. // the bottom
  328. //
  329. dwStyle |= WS_CLIPSIBLINGS;
  330. return dwStyle;
  331. } // end of wxButton::OS2GetStyle
  332. MRESULT wxButton::WindowProc( WXUINT uMsg,
  333. WXWPARAM wParam,
  334. WXLPARAM lParam )
  335. {
  336. //
  337. // When we receive focus, we want to temporary become the default button in
  338. // our parent panel so that pressing "Enter" would activate us -- and when
  339. // losing it we should restore the previous default button as well
  340. //
  341. if (uMsg == WM_SETFOCUS)
  342. {
  343. if (SHORT1FROMMP(lParam) == TRUE)
  344. SetTmpDefault();
  345. else
  346. UnsetTmpDefault();
  347. //
  348. // Let the default processign take place too
  349. //
  350. }
  351. else if (uMsg == WM_BUTTON1DBLCLK)
  352. {
  353. //
  354. // Emulate a click event to force an owner-drawn button to change its
  355. // appearance - without this, it won't do it
  356. //
  357. (void)wxControl::OS2WindowProc( WM_BUTTON1DOWN
  358. ,wParam
  359. ,lParam
  360. );
  361. //
  362. // And conitnue with processing the message normally as well
  363. //
  364. }
  365. //
  366. // Let the base class do all real processing
  367. //
  368. return (wxControl::OS2WindowProc( uMsg
  369. ,wParam
  370. ,lParam
  371. ));
  372. } // end of wxWindowProc