Code::Blocks  SVN r11506
infowindow.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 10636 $
6  * $Id: infowindow.cpp 10636 2015-12-29 16:30:40Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/infowindow.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include <wx/intl.h>
14  #include <wx/stattext.h>
15  #include <wx/sizer.h>
16  #include <wx/settings.h>
17  #include <wx/statbmp.h>
18  #include <wx/panel.h>
19  #include <wx/frame.h>
20  #include "infowindow.h"
21  #include "manager.h"
22 #endif
23 
24 #include <limits>
25 #include <wx/display.h>
26 
27 BEGIN_EVENT_TABLE(InfoWindow, wxInfoWindowBase)
28 EVT_TIMER(-1, InfoWindow::OnTimer)
29 EVT_MOTION(InfoWindow::OnMove)
30 EVT_LEFT_DOWN(InfoWindow::OnClick)
31 EVT_RIGHT_DOWN(InfoWindow::OnClick)
32 END_EVENT_TABLE()
33 
34 const wxColour titleBackground(96,96,96); // dark grey
35 const wxColour textBackground(255,255,160); // yellowish
36 const wxColour textForeground(0, 0, 0); // black for the text color
37 
38 
39 const char *iBitmap[] = {
40 "20 20 38 1",
41 " c #606060",
42 ". c gray38",
43 "X c #646464",
44 "o c #656565",
45 "O c gray40",
46 "+ c gray45",
47 "@ c gray50",
48 "# c blue",
49 "$ c #0808FF",
50 "% c #0A0AFF",
51 "& c #0B0BFF",
52 "* c #2121FF",
53 "= c #2828FF",
54 "- c #3838FF",
55 "; c #4545FF",
56 ": c #4646FF",
57 "> c #5656FF",
58 ", c #5959FF",
59 "< c gray51",
60 "1 c #8E8E8E",
61 "2 c gray59",
62 "3 c #9191A7",
63 "4 c #8888EF",
64 "5 c #8080F7",
65 "6 c #8282F7",
66 "7 c #8787FE",
67 "8 c #8A8AFE",
68 "9 c #9696FE",
69 "0 c #9797FF",
70 "q c #ABABFF",
71 "w c #CDCDFF",
72 "e c #D5D5FF",
73 "r c #E4E4F9",
74 "t c gray96",
75 "y c #F6F6F6",
76 "u c gray97",
77 "i c #F8F8F8",
78 "p c gray100",
79 " X+<1221<+O ",
80 " X+35,=&&=,63+X ",
81 " X@4:########:4@X ",
82 " X@5*#&>0ww0,&#*5@X ",
83 " +4*#-qppppppq:#*4+ ",
84 "X3:#:eppp##pppe:#:3X",
85 "+6#&qpppp##ppppq&#6+",
86 "<,#,ppppp##ppppp,#,@",
87 "1=#9ppppp##ppppp0#=1",
88 "2&#wppppp##pppppw#&2",
89 "i&#wppppp##pppppw#&u",
90 "i=#9ppppp##ppppp0#=u",
91 "u,#>pppppppppppp>#,y",
92 "y8#&qpppp##ppppq$#8y",
93 "yr:#:eppp##pppe:#:rt",
94 "yy9*#:qppppppq:#*9yt",
95 "yyy7*#$>0ww0>&#*7ytt",
96 "ttyy9:########:9yytt",
97 "ttttyr8,=&&=,8ryyttt",
98 "ttttyyyyiuuuuyyyyttt"
99 };
100 
101 namespace {
102 
103 class Stacker
104 {
105  std::list<int> widths;
106 
107  public:
108 
109  int StackMe(int mySize)
110  {
111  mySize += 3;
112  int pos = 0;
113 
114  if(!widths.empty())
115  pos = *(std::max_element(widths.begin(), widths.end()));
116 
117  widths.push_back(pos + mySize);
118  return pos + mySize;
119  };
120 
121  void ReleaseMe(int myPos)
122  {
123  std::list<int>::iterator it = std::find(widths.begin(), widths.end(), myPos);
124  if(it != widths.end())
125  widths.erase(it);
126  };
127 };
128 
129 static Stacker stacker;
130 
131 static std::list<wxString> active_messages;
132 static unsigned lastDisplay = std::numeric_limits<unsigned>::max();
133 static wxRect displayGeometry;
134 }
135 
136 namespace
137 {
138  // while in windows world, sleep(1) takes anywhere between 20-50 milliseconds,
139  // in linux sleep(1) means sleep 1 millisecond.
140  // so we need conditional compilation here in order for the scrolling effect to be
141  // visible under non-windows platforms :)
142  static const int scroll_millis = platform::windows ? 1 : 5;
143 }
144 
146 {
147  void OnEvent(wxMouseEvent& e){e.ResumePropagation(10); e.Skip();};
148  DECLARE_EVENT_TABLE();
149  public:
150  ForwardingTextControl(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0) : wxStaticText(parent, id, label, pos, size, style){};
151 };
152 
153 BEGIN_EVENT_TABLE(ForwardingTextControl, wxStaticText)
154 EVT_MOUSE_EVENTS(ForwardingTextControl::OnEvent)
155 END_EVENT_TABLE()
156 
157 
158 InfoWindow::InfoWindow(const wxString& title, const wxString& message, unsigned int delay, unsigned int hysteresis)
159  : wxInfoWindowBase(Manager::Get()->GetAppWindow(),
160 #if !wxUSE_POPUPWIN
161  wxID_ANY, wxEmptyString, wxPoint(-21,-21), wxSize(20,20),
162 #endif
164  m_timer(new wxTimer(this, 0)), status(0), m_delay(delay), ks(2)
165  {
166  my_message_iterator = active_messages.insert(active_messages.begin(), message);
167 
168  wxBoxSizer *bs = new wxBoxSizer(wxVERTICAL);
169 
170  wxWindow* o = nullptr;
171 
172  ForwardingTextControl *titleC = nullptr;
173 
174  if(platform::gtk)
175  {
176  wxBoxSizer *pbs = new wxBoxSizer(wxVERTICAL);
178  pnl->SetBackgroundColour(titleBackground);
180  pbs->Add(titleC, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5);
181  pnl->SetSizer(pbs);
182  pbs->SetSizeHints(pnl);
183  o = pnl;
184  }
185  else
186  {
187  titleC = new ForwardingTextControl(this, -1, title, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
188  titleC->SetBackgroundColour(titleBackground);
189  o = titleC;
190  }
191 
192  titleC->SetForegroundColour(*wxWHITE);
194  bs->Add(o, 0, wxGROW, 5);
195 
197  text->SetBackgroundColour(textBackground);
198  text->SetForegroundColour(textForeground);
199  bs->Add(text, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 12);
200  SetBackgroundColour(textBackground);
201  SetSizer(bs);
202  bs->SetSizeHints(this);
203  Layout();
204 
205  if(!platform::gtk)
206  {
207  // since we used a panel, no more bitmap :(
208  new wxStaticBitmap(this, -1, wxBitmap(iBitmap), wxPoint(4, o->GetRect().GetBottom() - 9));
209  }
210  wxCoord w, h;
211  GetClientSize(&w, &h);
212 
213  pos = stacker.StackMe(w);
214 
215  // setup variables first time we enter here
216  unsigned displayNo = wxDisplay::GetFromWindow(Manager::Get()->GetAppWindow());
217  if (displayNo != lastDisplay)
218  {
219  wxDisplay display(displayNo);
220  wxRect area = display.GetClientArea();
221  displayGeometry = display.GetGeometry();
222  displayGeometry = displayGeometry.Intersect(area);
223  lastDisplay = displayNo;
224  }
225 
226  left = displayGeometry.x + displayGeometry.width - pos;
227  hMin = displayGeometry.GetBottom() - h;
228  top = displayGeometry.GetBottom();
229 
230  Move(left, top);
231 
232  Show();
233  m_timer->Start(hysteresis, false);
234  }
235 
236 
238 {
239  delete m_timer;
240  stacker.ReleaseMe(pos);
241 
242  active_messages.erase(my_message_iterator);
243 }
244 
246 {
247  switch(status)
248  {
249  case 0:
250  status = 1;
251  m_timer->Start(scroll_millis, false);
252  break;
253  case 1:
254  top -= 2;
255  Move(left, top);
256  if(top <= hMin)
257  {
258  status = 2;
259  m_timer->Start(m_delay, true);
260  }
261  break;
262  case 2:
263  status = 3;
264  m_timer->Start(scroll_millis, false);
265  break;
266  case 3:
267  top += ks;
268  Move(left, top);
269  if(top > displayGeometry.GetBottom())
270  {
271  Hide();
272  Destroy();
273  }
274  break;
275  default:
276  break;
277  };
278 }
279 
281 {
282  if(status == 2)
283  m_timer->Start(m_delay, true);
284 }
285 
287 {
288  ks = 6;
289  status = 3;
290  m_timer->Start(scroll_millis, false);
291 }
292 
293 // static
294 void InfoWindow::Display(const wxString& title, const wxString& message, unsigned int delay, unsigned int hysteresis)
295 {
296  if (std::find(active_messages.begin(), active_messages.end(), message) != active_messages.end())
297  {
298  const wxString dups = _T("Multiple information windows with the same\nmessage have been suppressed.");
299  if (std::find(active_messages.begin(), active_messages.end(), dups) == active_messages.end())
300  Display(_T("Info"), dups, delay);
301  return; // currently displaying already
302  }
303  new InfoWindow(title, message, delay, hysteresis);
304 }
static void Display(const wxString &title, const wxString &message, unsigned int delay=5000, unsigned int hysteresis=1)
Definition: infowindow.cpp:294
~InfoWindow() override
Definition: infowindow.cpp:237
const wxColour textForeground(0, 0, 0)
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
void OnTimer(wxTimerEvent &e)
Definition: infowindow.cpp:245
const wxColour textBackground(255, 255, 160)
const wxColour titleBackground(96, 96, 96)
void OnClick(wxMouseEvent &e)
Definition: infowindow.cpp:286
wxRect GetClientArea() const
#define _T(string)
void OnMove(wxMouseEvent &e)
Definition: infowindow.cpp:280
void OnEvent(wxMouseEvent &e)
Definition: infowindow.cpp:147
wxRect GetGeometry() const
wxSizerItem * Add(wxWindow *window, const wxSizerFlags &flags)
#define wxWS_EX_TRANSIENT
const wxSize wxDefaultSize
const wxPoint wxDefaultPosition
wxColour * wxWHITE
wxString wxEmptyString
ForwardingTextControl(wxWindow *parent, wxWindowID id, const wxString &label, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0)
Definition: infowindow.cpp:150
static int GetFromWindow(const wxWindow *win)
#define wxSIMPLE_BORDER
const char * iBitmap[]
Definition: infowindow.cpp:39
void SetSizeHints(wxWindow *window)
#define wxCLIP_CHILDREN
wxRect & Intersect(const wxRect &rect)
int wxCoord
int wxWindowID