]> git.saurik.com Git - wxWidgets.git/blame - src/stc/PlatWX.cpp
Various changes to make pop up menus work
[wxWidgets.git] / src / stc / PlatWX.cpp
CommitLineData
9ce192d4
RD
1// Scintilla source code edit control
2// PlatWX.cxx - implementation of platform facilities on wxWindows
3// Copyright 1998-1999 by Neil Hodgson <neilh@scintilla.org>
4// Robin Dunn <robin@aldunn.com>
5// The License.txt file describes the conditions under which this software may be distributed.
6
f6bcfd97 7#include <ctype.h>
9ce192d4
RD
8
9#include "Platform.h"
10#include "wx/stc/stc.h"
11
f97d84a6
RD
12
13#ifdef __WXGTK__
14#include <gtk/gtk.h>
15#endif
16
9ce192d4 17Point Point::FromLong(long lpoint) {
f6bcfd97 18 return Point(lpoint & 0xFFFF, lpoint >> 16);
9ce192d4
RD
19}
20
21wxRect wxRectFromPRectangle(PRectangle prc) {
22 wxRect rc(prc.left, prc.top,
21156596 23 prc.right-prc.left, prc.bottom-prc.top);
9ce192d4
RD
24 return rc;
25}
26
27PRectangle PRectangleFromwxRect(wxRect rc) {
bec17edf
RD
28 return PRectangle(rc.GetLeft(), rc.GetTop(),
29 rc.GetRight()+1, rc.GetBottom()+1);
9ce192d4
RD
30}
31
32Colour::Colour(long lcol) {
33 co.Set(lcol & 0xff, (lcol >> 8) & 0xff, (lcol >> 16) & 0xff);
34}
35
36Colour::Colour(unsigned int red, unsigned int green, unsigned int blue) {
37 co.Set(red, green, blue);
38}
39
40bool Colour::operator==(const Colour &other) const {
41 return co == other.co;
42}
43
44long Colour::AsLong() const {
45 return (((long)co.Blue() << 16) |
46 ((long)co.Green() << 8) |
47 ((long)co.Red()));
48}
49
50unsigned int Colour::GetRed() {
51 return co.Red();
52}
53
54unsigned int Colour::GetGreen() {
55 return co.Green();
56}
57
58unsigned int Colour::GetBlue() {
59 return co.Blue();
60}
61
62Palette::Palette() {
63 used = 0;
64 allowRealization = false;
65}
66
67Palette::~Palette() {
68 Release();
69}
70
71void Palette::Release() {
72 used = 0;
73}
74
75// This method either adds a colour to the list of wanted colours (want==true)
76// or retrieves the allocated colour back to the ColourPair.
77// This is one method to make it easier to keep the code for wanting and retrieving in sync.
78void Palette::WantFind(ColourPair &cp, bool want) {
79 if (want) {
80 for (int i=0; i < used; i++) {
81 if (entries[i].desired == cp.desired)
82 return;
83 }
84
85 if (used < numEntries) {
86 entries[used].desired = cp.desired;
87 entries[used].allocated = cp.desired;
88 used++;
89 }
90 } else {
91 for (int i=0; i < used; i++) {
92 if (entries[i].desired == cp.desired) {
93 cp.allocated = entries[i].allocated;
94 return;
95 }
96 }
97 cp.allocated = cp.desired;
98 }
99}
100
101void Palette::Allocate(Window &) {
102 if (allowRealization) {
103 }
104}
105
106
107Font::Font() {
108 id = 0;
109 ascent = 0;
110}
111
112Font::~Font() {
113}
114
f6bcfd97 115void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
65ec6247
RD
116 // TODO: what to do about the characterSet?
117
9ce192d4
RD
118 Release();
119 id = new wxFont(size,
120 wxDEFAULT,
121 italic ? wxITALIC : wxNORMAL,
122 bold ? wxBOLD : wxNORMAL,
123 false,
f6bcfd97
BP
124 faceName,
125 wxFONTENCODING_DEFAULT);
9ce192d4
RD
126}
127
128
129void Font::Release() {
130 if (id)
131 delete id;
132 id = 0;
133}
134
135
136Surface::Surface() :
137 hdc(0), hdcOwned(0), bitmap(0),
138 x(0), y(0) {
139}
140
141Surface::~Surface() {
142 Release();
143}
144
145void Surface::Release() {
146 if (bitmap) {
147 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
148 delete bitmap;
149 bitmap = 0;
150 }
151 if (hdcOwned) {
152 delete hdc;
153 hdc = 0;
154 hdcOwned = false;
155 }
156}
157
158
159bool Surface::Initialised() {
160 return hdc != 0;
161}
162
163void Surface::Init() {
164 Release();
165 hdc = new wxMemoryDC();
166 hdcOwned = true;
9ce192d4
RD
167}
168
169void Surface::Init(SurfaceID hdc_) {
170 Release();
171 hdc = hdc_;
9ce192d4
RD
172}
173
174void Surface::InitPixMap(int width, int height, Surface *surface_) {
175 Release();
176 hdc = new wxMemoryDC(surface_->hdc);
177 hdcOwned = true;
2beb01db
RD
178 if (width < 1) width = 1;
179 if (height < 1) height = 1;
21156596 180 bitmap = new wxBitmap(width, height);
9ce192d4 181 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
9ce192d4
RD
182}
183
184void Surface::PenColour(Colour fore) {
185 hdc->SetPen(wxPen(fore.co, 1, wxSOLID));
186}
187
188void Surface::BrushColor(Colour back) {
189 hdc->SetBrush(wxBrush(back.co, wxSOLID));
190}
191
192void Surface::SetFont(Font &font_) {
21156596 193 if (font_.GetID()) {
f6bcfd97
BP
194 hdc->SetFont(*font_.GetID());
195 }
9ce192d4
RD
196}
197
198int Surface::LogPixelsY() {
199 return hdc->GetPPI().y;
200}
201
f6bcfd97
BP
202
203int Surface::DeviceHeightFont(int points) {
9968ba85 204 return points;
f6bcfd97
BP
205}
206
207
9ce192d4
RD
208void Surface::MoveTo(int x_, int y_) {
209 x = x_;
210 y = y_;
211}
212
213void Surface::LineTo(int x_, int y_) {
214 hdc->DrawLine(x,y, x_,y_);
215 x = x_;
216 y = y_;
217}
218
219void Surface::Polygon(Point *pts, int npts, Colour fore,
220 Colour back) {
221 PenColour(fore);
222 BrushColor(back);
223 hdc->DrawPolygon(npts, (wxPoint*)pts);
224}
225
226void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) {
227 PenColour(fore);
228 BrushColor(back);
229 hdc->DrawRectangle(wxRectFromPRectangle(rc));
230}
231
232void Surface::FillRectangle(PRectangle rc, Colour back) {
233 BrushColor(back);
234 hdc->SetPen(*wxTRANSPARENT_PEN);
235 hdc->DrawRectangle(wxRectFromPRectangle(rc));
236}
237
238void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
239 wxBrush br;
240 if (surfacePattern.bitmap)
241 br = wxBrush(*surfacePattern.bitmap);
242 else // Something is wrong so display in red
243 br = wxBrush(*wxRED, wxSOLID);
244 hdc->SetPen(*wxTRANSPARENT_PEN);
245 hdc->SetBrush(br);
246 hdc->DrawRectangle(wxRectFromPRectangle(rc));
247}
248
249void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
250 PenColour(fore);
251 BrushColor(back);
f6bcfd97 252 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
9ce192d4
RD
253}
254
255void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
256 PenColour(fore);
257 BrushColor(back);
258 hdc->DrawEllipse(wxRectFromPRectangle(rc));
259}
260
261void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
f6bcfd97
BP
262 wxRect r = wxRectFromPRectangle(rc);
263 hdc->Blit(r.x, r.y, r.width, r.height,
9ce192d4
RD
264 surfaceSource.hdc, from.x, from.y, wxCOPY);
265}
266
267void Surface::DrawText(PRectangle rc, Font &font, int ybase,
268 const char *s, int len, Colour fore, Colour back) {
269 SetFont(font);
270 hdc->SetTextForeground(fore.co);
271 hdc->SetTextBackground(back.co);
272 FillRectangle(rc, back);
273
274 // ybase is where the baseline should be, but wxWin uses the upper left
275 // corner, so I need to calculate the real position for the text...
276 hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
277}
278
279void Surface::DrawTextClipped(PRectangle rc, Font &font, int ybase, const char *s, int len, Colour fore, Colour back) {
280 SetFont(font);
281 hdc->SetTextForeground(fore.co);
282 hdc->SetTextBackground(back.co);
283 FillRectangle(rc, back);
284 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
285
286 // see comments above
287 hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
288 hdc->DestroyClippingRegion();
289}
290
291int Surface::WidthText(Font &font, const char *s, int len) {
292 SetFont(font);
293 int w;
294 int h;
295 hdc->GetTextExtent(wxString(s, len), &w, &h);
296 return w;
297}
298
299void Surface::MeasureWidths(Font &font, const char *s, int len, int *positions) {
300 SetFont(font);
301 int totalWidth = 0;
302 for (int i=0; i<len; i++) {
303 int w;
304 int h;
305 hdc->GetTextExtent(s[i], &w, &h);
306 totalWidth += w;
307 positions[i] = totalWidth;
308 }
309}
310
311int Surface::WidthChar(Font &font, char ch) {
312 SetFont(font);
313 int w;
314 int h;
315 hdc->GetTextExtent(ch, &w, &h);
316 return w;
317}
318
319#define EXTENT_TEST " `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
320
321int Surface::Ascent(Font &font) {
322 SetFont(font);
323 int w, h, d, e;
324 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
325 font.ascent = h - d;
326 return font.ascent;
327}
328
329int Surface::Descent(Font &font) {
330 SetFont(font);
331 int w, h, d, e;
332 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
333 return d;
334}
335
336int Surface::InternalLeading(Font &font) {
337 return 0;
338}
339
340int Surface::ExternalLeading(Font &font) {
341 SetFont(font);
342 int w, h, d, e;
343 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
344 return e;
345}
346
347int Surface::Height(Font &font) {
348 SetFont(font);
349 return hdc->GetCharHeight();
350}
351
352int Surface::AverageCharWidth(Font &font) {
353 SetFont(font);
354 return hdc->GetCharWidth();
355}
356
357int Surface::SetPalette(Palette *pal, bool inBackGround) {
65ec6247 358 return 0;
9ce192d4
RD
359}
360
361void Surface::SetClip(PRectangle rc) {
362 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
363}
364
f6bcfd97 365void Surface::FlushCachedState() {
f6bcfd97 366}
9ce192d4
RD
367
368Window::~Window() {
369}
370
371void Window::Destroy() {
372 if (id)
373 id->Destroy();
374 id = 0;
375}
376
377bool Window::HasFocus() {
378 return wxWindow::FindFocus() == id;
379}
380
381PRectangle Window::GetPosition() {
382 wxRect rc(id->GetPosition(), id->GetSize());
383 return PRectangleFromwxRect(rc);
384}
385
386void Window::SetPosition(PRectangle rc) {
f6bcfd97
BP
387 wxRect r = wxRectFromPRectangle(rc);
388 id->SetSize(r);
9ce192d4
RD
389}
390
391void Window::SetPositionRelative(PRectangle rc, Window) {
392 SetPosition(rc); // ????
393}
394
395PRectangle Window::GetClientPosition() {
396 wxSize sz = id->GetClientSize();
21156596 397 return PRectangle(0, 0, sz.x, sz.y);
9ce192d4
RD
398}
399
400void Window::Show(bool show) {
401 id->Show(show);
402}
403
404void Window::InvalidateAll() {
405 id->Refresh(false);
406}
407
408void Window::InvalidateRectangle(PRectangle rc) {
f6bcfd97
BP
409 wxRect r = wxRectFromPRectangle(rc);
410 id->Refresh(false, &r);
9ce192d4
RD
411}
412
413void Window::SetFont(Font &font) {
414 id->SetFont(*font.GetID());
415}
416
417void Window::SetCursor(Cursor curs) {
418 int cursorId;
419
420 switch (curs) {
421 case cursorText:
422 cursorId = wxCURSOR_IBEAM;
423 break;
424 case cursorArrow:
425 cursorId = wxCURSOR_ARROW;
426 break;
427 case cursorUp:
428 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
429 break;
430 case cursorWait:
431 cursorId = wxCURSOR_WAIT;
432 break;
433 case cursorHoriz:
434 cursorId = wxCURSOR_SIZEWE;
435 break;
436 case cursorVert:
437 cursorId = wxCURSOR_SIZENS;
438 break;
439 case cursorReverseArrow:
440 cursorId = wxCURSOR_POINT_RIGHT;
441 break;
442 default:
443 cursorId = wxCURSOR_ARROW;
444 break;
445 }
446
447 id->SetCursor(wxCursor(cursorId));
448}
449
450
451void Window::SetTitle(const char *s) {
452 id->SetTitle(s);
453}
454
455
769a9cb2
RD
456//----------------------------------------------------------------------
457// Helper classes for ListBox
458
459// A wxListBox that gives focus to its parent if it gets it.
f97d84a6
RD
460class wxSTCListBox : public wxListBox {
461public:
462 wxSTCListBox(wxWindow* parent, wxWindowID id)
463 : wxListBox(parent, id, wxDefaultPosition, wxDefaultSize,
769a9cb2 464 0, NULL, wxLB_SINGLE | wxSIMPLE_BORDER)
f97d84a6
RD
465 {}
466
467 void OnFocus(wxFocusEvent& event) {
468 GetParent()->SetFocus();
469 event.Skip();
470 }
471
f97d84a6
RD
472private:
473 DECLARE_EVENT_TABLE()
474};
475
476BEGIN_EVENT_TABLE(wxSTCListBox, wxListBox)
477 EVT_SET_FOCUS(wxSTCListBox::OnFocus)
478END_EVENT_TABLE()
479
480
769a9cb2
RD
481
482// A window to place the listbox upon. If wxPopupWindow is supported then
483// that will be used so the listbox can extend beyond the client area of the
484// wxSTC if needed.
485
486#if wxUSE_POPUPWIN
487#include <wx/popupwin.h>
488#define wxSTCListBoxWinBase wxPopupWindow
489#define param2 wxBORDER_NONE // popup's 2nd param is flags
490#else
491#define wxSTCListBoxWinBase wxWindow
492#define param2 -1 // wxWindows 2nd param is ID
493#endif
494
495class wxSTCListBoxWin : public wxSTCListBoxWinBase {
496public:
497 wxSTCListBoxWin(wxWindow* parent, wxWindowID id)
498 : wxSTCListBoxWinBase(parent, param2) {
499 lb = new wxSTCListBox(this, id);
500 }
501
502 void OnSize(wxSizeEvent& event) {
503 lb->SetSize(GetSize());
504 }
505 void OnFocus(wxFocusEvent& event) {
506 GetParent()->SetFocus();
507 event.Skip();
508 }
509
510 wxListBox* GetLB() { return lb; }
511
512#if wxUSE_POPUPWIN
513 virtual void DoSetSize(int x, int y,
514 int width, int height,
515 int sizeFlags = wxSIZE_AUTO) {
516 if (x != -1)
517 GetParent()->ClientToScreen(&x, NULL);
518 if (y != -1)
519 GetParent()->ClientToScreen(NULL, &y);
520 wxSTCListBoxWinBase::DoSetSize(x, y, width, height, sizeFlags);
521 }
522#endif
523
524private:
525 wxSTCListBox* lb;
526 DECLARE_EVENT_TABLE()
527};
528
529BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxSTCListBoxWinBase)
530 EVT_SIZE (wxSTCListBoxWin::OnSize)
531 EVT_SET_FOCUS (wxSTCListBoxWin::OnFocus)
532END_EVENT_TABLE()
533
534
535#define GETLB(win) (((wxSTCListBoxWin*)win)->GetLB())
536
537//----------------------------------------------------------------------
538
9ce192d4
RD
539ListBox::ListBox() {
540}
541
542ListBox::~ListBox() {
543}
544
545void ListBox::Create(Window &parent, int ctrlID) {
769a9cb2 546 id = new wxSTCListBoxWin(parent.id, ctrlID);
9ce192d4
RD
547}
548
f3c2c221 549void ListBox::SetVisibleRows(int rows) {
769a9cb2 550 desiredVisibleRows = rows;
f3c2c221
RD
551}
552
d134f170 553PRectangle ListBox::GetDesiredRect() {
769a9cb2 554 wxSize sz = GETLB(id)->GetBestSize();
d134f170
RD
555 PRectangle rc;
556 rc.top = 0;
557 rc.left = 0;
f3c2c221
RD
558 if (sz.x > 400)
559 sz.x = 400;
9af175d2
RD
560 if (sz.y > 160) // TODO: Use desiredVisibleRows??
561 sz.y = 160;
d134f170
RD
562 rc.right = sz.x;
563 rc.bottom = sz.y;
d134f170
RD
564 return rc;
565}
566
567void ListBox::SetAverageCharWidth(int width) {
568 aveCharWidth = width;
569}
570
571void ListBox::SetFont(Font &font) {
769a9cb2 572 GETLB(id)->SetFont(*font.GetID());
d134f170
RD
573}
574
9ce192d4 575void ListBox::Clear() {
769a9cb2 576 GETLB(id)->Clear();
9ce192d4
RD
577}
578
579void ListBox::Append(char *s) {
769a9cb2 580 GETLB(id)->Append(s);
9ce192d4
RD
581}
582
583int ListBox::Length() {
769a9cb2 584 return GETLB(id)->GetCount();
9ce192d4
RD
585}
586
587void ListBox::Select(int n) {
769a9cb2 588 GETLB(id)->SetSelection(n);
f97d84a6
RD
589#ifdef __WXGTK__
590 if (n > 4)
591 n = n - 4;
592 else
593 n = 1;
769a9cb2 594 GETLB(id)->SetFirstItem(n);
f97d84a6 595#endif
9ce192d4
RD
596}
597
598int ListBox::GetSelection() {
769a9cb2 599 return GETLB(id)->GetSelection();
9ce192d4
RD
600}
601
602int ListBox::Find(const char *prefix) {
b8b0e402 603 // No longer used
f6bcfd97 604 return -1;
9ce192d4
RD
605}
606
607void ListBox::GetValue(int n, char *value, int len) {
769a9cb2 608 wxString text = GETLB(id)->GetString(n);
9ce192d4
RD
609 strncpy(value, text.c_str(), len);
610 value[len-1] = '\0';
611}
612
613void ListBox::Sort() {
9ce192d4
RD
614}
615
616
617Menu::Menu() : id(0) {
618}
619
620void Menu::CreatePopUp() {
621 Destroy();
622 id = new wxMenu();
623}
624
625void Menu::Destroy() {
626 if (id)
627 delete id;
628 id = 0;
629}
630
631void Menu::Show(Point pt, Window &w) {
632 w.GetID()->PopupMenu(id, pt.x - 4, pt.y);
633 Destroy();
634}
635
636
637Colour Platform::Chrome() {
638 wxColour c;
e1c6c6ae 639 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
9ce192d4
RD
640 return Colour(c.Red(), c.Green(), c.Blue());
641}
642
643Colour Platform::ChromeHighlight() {
644 wxColour c;
e1c6c6ae 645 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
9ce192d4
RD
646 return Colour(c.Red(), c.Green(), c.Blue());
647}
648
649const char *Platform::DefaultFont() {
650 return wxNORMAL_FONT->GetFaceName();
651}
652
653int Platform::DefaultFontSize() {
654 return 8;
655}
656
657unsigned int Platform::DoubleClickTime() {
658 return 500; // **** ::GetDoubleClickTime();
659}
660
661void Platform::DebugDisplay(const char *s) {
662 wxLogDebug(s);
663}
664
665bool Platform::IsKeyDown(int key) {
666 return false; // I don't think we'll need this.
667}
668
669long Platform::SendScintilla(WindowID w,
670 unsigned int msg,
671 unsigned long wParam,
672 long lParam) {
673
674 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
675 return stc->SendMsg(msg, wParam, lParam);
676}
677
678
679// These are utility functions not really tied to a platform
680
681int Platform::Minimum(int a, int b) {
682 if (a < b)
683 return a;
684 else
685 return b;
686}
687
688int Platform::Maximum(int a, int b) {
689 if (a > b)
690 return a;
691 else
692 return b;
693}
694
695#define TRACE
696
697void Platform::DebugPrintf(const char *format, ...) {
698#ifdef TRACE
699 char buffer[2000];
700 va_list pArguments;
701 va_start(pArguments, format);
702 vsprintf(buffer,format,pArguments);
703 va_end(pArguments);
704 Platform::DebugDisplay(buffer);
705#endif
706}
707
65ec6247
RD
708
709static bool assertionPopUps = true;
710
711bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
712 bool ret = assertionPopUps;
713 assertionPopUps = assertionPopUps_;
714 return ret;
715}
716
717void Platform::Assert(const char *c, const char *file, int line) {
718 char buffer[2000];
719 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
720 if (assertionPopUps) {
721 int idButton = wxMessageBox(buffer, "Assertion failure",
722 wxICON_HAND | wxOK);
723// if (idButton == IDRETRY) {
724// ::DebugBreak();
725// } else if (idButton == IDIGNORE) {
726// // all OK
727// } else {
728// abort();
729// }
730 } else {
731 strcat(buffer, "\r\n");
732 Platform::DebugDisplay(buffer);
733 abort();
734 }
735}
736
737
9ce192d4
RD
738int Platform::Clamp(int val, int minVal, int maxVal) {
739 if (val > maxVal)
740 val = maxVal;
741 if (val < minVal)
742 val = minVal;
743 return val;
744}
745
746
747
748
749
750