mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-23 02:25:52 -04:00
301212005c
Finished implementation of ResourcesManager. git-svn-id: svn://localhost@541 8062f311-0dae-4547-b526-b8ab9ac864a5
867 lines
26 KiB
C++
867 lines
26 KiB
C++
#include "GDAuiTabArt.h"
|
|
#include <wx/aui/framemanager.h>
|
|
#include <wx/aui/dockart.h>
|
|
#include <wx/aui/floatpane.h>
|
|
#include <wx/control.h>
|
|
#include <wx/image.h>
|
|
#include <wx/dc.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/menu.h>
|
|
#include <wx/renderer.h>
|
|
#include <iostream>
|
|
#include <wx/dcbuffer.h>
|
|
|
|
// the original wx functions live in dockart.cpp -- need to redefine them
|
|
unsigned char gdAuiBlendColour(unsigned char fg, unsigned char bg, double alpha)
|
|
{
|
|
double result = bg + (alpha * (fg - bg));
|
|
if (result < 0.0)
|
|
result = 0.0;
|
|
if (result > 255)
|
|
result = 255;
|
|
return (unsigned char)result;
|
|
}
|
|
|
|
wxColor gdAuiStepColour(const wxColor& c, int ialpha)
|
|
{
|
|
if (ialpha == 100)
|
|
return c;
|
|
|
|
if (!c.IsOk()) return c;
|
|
|
|
unsigned char r = c.Red(),
|
|
g = c.Green(),
|
|
b = c.Blue();
|
|
unsigned char bg;
|
|
|
|
// ialpha is 0..200 where 0 is completely black
|
|
// and 200 is completely white and 100 is the same
|
|
// convert that to normal alpha 0.0 - 1.0
|
|
ialpha = wxMin(ialpha, 200);
|
|
ialpha = wxMax(ialpha, 0);
|
|
double alpha = ((double)(ialpha - 100.0))/100.0;
|
|
|
|
if (ialpha > 100)
|
|
{
|
|
// blend with white
|
|
bg = 255;
|
|
alpha = 1.0 - alpha; // 0 = transparent fg; 1 = opaque fg
|
|
}
|
|
else
|
|
{
|
|
// blend with black
|
|
bg = 0;
|
|
alpha = 1.0 + alpha; // 0 = transparent fg; 1 = opaque fg
|
|
}
|
|
|
|
r = gdAuiBlendColour(r, bg, alpha);
|
|
g = gdAuiBlendColour(g, bg, alpha);
|
|
b = gdAuiBlendColour(b, bg, alpha);
|
|
|
|
return wxColour(r, g, b);
|
|
}
|
|
|
|
wxBitmap gdAuiBitmapFromBits(const unsigned char bits[], int w, int h,
|
|
const wxColour& color)
|
|
{
|
|
wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
|
|
img.Replace(0,0,0,123,123,123);
|
|
img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
|
|
img.SetMaskColour(123,123,123);
|
|
return wxBitmap(img);
|
|
}
|
|
|
|
wxString gdAuiChopText(wxDC& dc, const wxString& text, int max_size)
|
|
{
|
|
wxCoord x,y;
|
|
|
|
// first check if the text fits with no problems
|
|
dc.GetTextExtent(text, &x, &y);
|
|
if (x <= max_size)
|
|
return text;
|
|
|
|
size_t i, len = text.Length();
|
|
size_t last_good_length = 0;
|
|
for (i = 0; i < len; ++i)
|
|
{
|
|
wxString s = text.Left(i);
|
|
s += wxT("...");
|
|
|
|
dc.GetTextExtent(s, &x, &y);
|
|
if (x > max_size)
|
|
break;
|
|
|
|
last_good_length = i;
|
|
}
|
|
|
|
wxString ret = text.Left(last_good_length);
|
|
ret += wxT("...");
|
|
return ret;
|
|
}
|
|
|
|
static void DrawButtons(wxDC& dc,
|
|
const wxRect& _rect,
|
|
const wxBitmap& bmp,
|
|
const wxColour& bkcolour,
|
|
int button_state)
|
|
{
|
|
wxRect rect = _rect;
|
|
|
|
if (button_state == wxAUI_BUTTON_STATE_PRESSED)
|
|
{
|
|
rect.x++;
|
|
rect.y++;
|
|
}
|
|
|
|
if (button_state == wxAUI_BUTTON_STATE_HOVER ||
|
|
button_state == wxAUI_BUTTON_STATE_PRESSED)
|
|
{
|
|
dc.SetBrush(wxBrush(gdAuiStepColour(bkcolour, 120)));
|
|
dc.SetPen(wxPen(gdAuiStepColour(bkcolour, 75)));
|
|
|
|
// draw the background behind the button
|
|
dc.DrawRectangle(rect.x, rect.y, 15, 15);
|
|
}
|
|
|
|
// draw the button itself
|
|
dc.DrawBitmap(bmp, rect.x, rect.y, true);
|
|
}
|
|
|
|
static void IndentPressedBitmap(wxRect* rect, int button_state)
|
|
{
|
|
if (button_state == wxAUI_BUTTON_STATE_PRESSED)
|
|
{
|
|
rect->x++;
|
|
rect->y++;
|
|
}
|
|
}
|
|
|
|
// -- bitmaps --
|
|
|
|
#if defined( __WXMAC__ )
|
|
static unsigned char GDclose_bits[]={
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
|
|
0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
|
|
0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
|
|
#elif defined( __WXGTK__)
|
|
static unsigned char GDclose_bits[]={
|
|
0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
|
|
0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
|
|
0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
#else
|
|
static unsigned char GDclose_bits[]={
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
|
|
0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
#endif
|
|
|
|
static unsigned char GDleft_bits[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
|
|
0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
|
|
static unsigned char GDright_bits[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
|
|
0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
|
|
static unsigned char GDlist_bits[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
|
|
|
|
class GDAuiCommandCapture : public wxEvtHandler
|
|
{
|
|
public:
|
|
|
|
GDAuiCommandCapture() { m_last_id = 0; }
|
|
int GetCommandId() const { return m_last_id; }
|
|
|
|
bool ProcessEvent(wxEvent& evt)
|
|
{
|
|
if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
|
|
{
|
|
m_last_id = evt.GetId();
|
|
return true;
|
|
}
|
|
|
|
if (GetNextHandler())
|
|
return GetNextHandler()->ProcessEvent(evt);
|
|
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
int m_last_id;
|
|
};
|
|
|
|
|
|
|
|
GDAuiTabArt::GDAuiTabArt()
|
|
{
|
|
m_normal_font = *wxNORMAL_FONT;
|
|
m_selected_font = *wxNORMAL_FONT;
|
|
m_selected_font.SetWeight(wxBOLD);
|
|
m_measuring_font = m_selected_font;
|
|
|
|
m_fixed_tab_width = 100;
|
|
m_tab_ctrl_height = 0;
|
|
|
|
wxColor border_colour = gdAuiStepColour(m_base_colour, 75);
|
|
|
|
m_border_pen = wxPen(border_colour);
|
|
m_base_colour_pen = wxPen(m_base_colour);
|
|
m_base_colour_brush = wxBrush(m_base_colour);
|
|
|
|
m_active_close_bmp = gdAuiBitmapFromBits(GDclose_bits, 16, 16, *wxBLACK);
|
|
m_disabled_close_bmp = gdAuiBitmapFromBits(GDclose_bits, 16, 16, wxColour(128,128,128));
|
|
|
|
m_active_left_bmp = gdAuiBitmapFromBits(GDleft_bits, 16, 16, *wxBLACK);
|
|
m_disabled_left_bmp = gdAuiBitmapFromBits(GDleft_bits, 16, 16, wxColour(128,128,128));
|
|
|
|
m_active_right_bmp = gdAuiBitmapFromBits(GDright_bits, 16, 16, *wxBLACK);
|
|
m_disabled_right_bmp = gdAuiBitmapFromBits(GDright_bits, 16, 16, wxColour(128,128,128));
|
|
|
|
m_active_windowlist_bmp = gdAuiBitmapFromBits(GDlist_bits, 16, 16, *wxBLACK);
|
|
m_disabled_windowlist_bmp = gdAuiBitmapFromBits(GDlist_bits, 16, 16, wxColour(128,128,128));
|
|
|
|
m_flags = 0;
|
|
}
|
|
|
|
void GDAuiTabArt::SetColour(const wxColour& colour)
|
|
{
|
|
m_base_colour = colour;
|
|
|
|
wxColor border_colour = gdAuiStepColour(m_base_colour, 75);
|
|
|
|
m_border_pen = wxPen(border_colour);
|
|
m_base_colour_pen = wxPen(m_base_colour);
|
|
m_base_colour_brush = wxBrush(m_base_colour);
|
|
}
|
|
|
|
void GDAuiTabArt::SetActiveColour(const wxColour& colour)
|
|
{
|
|
m_active_colour = colour;
|
|
}
|
|
|
|
GDAuiTabArt::~GDAuiTabArt()
|
|
{
|
|
}
|
|
|
|
wxAuiTabArt* GDAuiTabArt::Clone()
|
|
{
|
|
GDAuiTabArt* art = new GDAuiTabArt;
|
|
art->SetNormalFont(m_normal_font);
|
|
art->SetSelectedFont(m_selected_font);
|
|
art->SetMeasuringFont(m_measuring_font);
|
|
art->SetColour(m_base_colour);
|
|
art->SetActiveColour(m_active_colour);
|
|
|
|
return art;
|
|
}
|
|
|
|
void GDAuiTabArt::SetFlags(unsigned int flags)
|
|
{
|
|
m_flags = flags;
|
|
}
|
|
|
|
void GDAuiTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
|
|
size_t tab_count)
|
|
{
|
|
m_fixed_tab_width = 100;
|
|
|
|
int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
|
|
|
|
if (m_flags & wxAUI_NB_CLOSE_BUTTON)
|
|
tot_width -= m_active_close_bmp.GetWidth();
|
|
if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
|
|
tot_width -= m_active_windowlist_bmp.GetWidth();
|
|
|
|
if (tab_count > 0)
|
|
{
|
|
m_fixed_tab_width = tot_width/(int)tab_count;
|
|
}
|
|
|
|
|
|
if (m_fixed_tab_width < 100)
|
|
m_fixed_tab_width = 100;
|
|
|
|
if (m_fixed_tab_width > tot_width/2)
|
|
m_fixed_tab_width = tot_width/2;
|
|
|
|
if (m_fixed_tab_width > 220)
|
|
m_fixed_tab_width = 220;
|
|
|
|
m_tab_ctrl_height = tab_ctrl_size.y;
|
|
}
|
|
|
|
|
|
void GDAuiTabArt::DrawBackground(wxDC& dc,
|
|
wxWindow* WXUNUSED(wnd),
|
|
const wxRect& rect)
|
|
{
|
|
// draw background
|
|
|
|
//Game Develop use a less visible gradient
|
|
wxColor top_color = gdAuiStepColour(m_base_colour, 120);
|
|
//Game Develop use a white background
|
|
wxColor bottom_color = *wxWHITE;
|
|
wxRect r;
|
|
|
|
if (m_flags &wxAUI_NB_BOTTOM)
|
|
r = wxRect(rect.x, rect.y, rect.width+2, rect.height);
|
|
// else if (m_flags &wxAUI_NB_LEFT) {}
|
|
// else if (m_flags &wxAUI_NB_RIGHT) {}
|
|
else //for wxAUI_NB_TOP
|
|
r = wxRect(rect.x, rect.y, rect.width+2, rect.height-3);
|
|
|
|
//Game Develop invert gradient for bottom
|
|
if (m_flags &wxAUI_NB_BOTTOM)
|
|
dc.GradientFillLinear(r, top_color, bottom_color, wxNORTH);
|
|
else //for wxAUI_NB_TOP
|
|
dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
|
|
|
|
|
|
// draw base lines
|
|
|
|
//Game Develop use a white background
|
|
dc.SetPen(*wxWHITE_PEN);
|
|
int y = rect.GetHeight();
|
|
int w = rect.GetWidth();
|
|
|
|
if (m_flags &wxAUI_NB_BOTTOM)
|
|
{
|
|
//Game Develop use a white background
|
|
dc.SetBrush(*wxWHITE_BRUSH);
|
|
dc.DrawRectangle(-1, 0, w+2, 4);
|
|
}
|
|
// else if (m_flags &wxAUI_NB_LEFT) {}
|
|
// else if (m_flags &wxAUI_NB_RIGHT) {}
|
|
else //for wxAUI_NB_TOP
|
|
{
|
|
//Game Develop use a white background
|
|
dc.SetBrush(*wxWHITE_BRUSH);
|
|
dc.DrawRectangle(-1, y-4, w+2, 4);
|
|
}
|
|
}
|
|
|
|
|
|
// DrawTab() draws an individual tab.
|
|
//
|
|
// dc - output dc
|
|
// in_rect - rectangle the tab should be confined to
|
|
// caption - tab's caption
|
|
// active - whether or not the tab is active
|
|
// out_rect - actual output rectangle
|
|
// x_extent - the advance x; where the next tab should start
|
|
|
|
void GDAuiTabArt::DrawTab(wxDC& dc,
|
|
wxWindow* wnd,
|
|
const wxAuiNotebookPage& page,
|
|
const wxRect& in_rect,
|
|
int close_button_state,
|
|
wxRect* out_tab_rect,
|
|
wxRect* out_button_rect,
|
|
int* x_extent)
|
|
{
|
|
wxCoord normal_textx, normal_texty;
|
|
wxCoord selected_textx, selected_texty;
|
|
wxCoord texty;
|
|
|
|
// if the caption is empty, measure some temporary text
|
|
wxString caption = page.caption;
|
|
if (caption.empty())
|
|
caption = wxT("Xj");
|
|
|
|
dc.SetFont(m_selected_font);
|
|
dc.GetTextExtent(caption, &selected_textx, &selected_texty);
|
|
|
|
dc.SetFont(m_normal_font);
|
|
dc.GetTextExtent(caption, &normal_textx, &normal_texty);
|
|
|
|
// figure out the size of the tab
|
|
wxSize tab_size = GetTabSize(dc,
|
|
wnd,
|
|
page.caption,
|
|
page.bitmap,
|
|
page.active,
|
|
close_button_state,
|
|
x_extent);
|
|
|
|
wxCoord tab_height = m_tab_ctrl_height - 3;
|
|
wxCoord tab_width = tab_size.x;
|
|
wxCoord tab_x = in_rect.x;
|
|
wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
|
|
|
|
|
|
caption = page.caption;
|
|
|
|
|
|
// select pen, brush and font for the tab to be drawn
|
|
|
|
if (page.active)
|
|
{
|
|
dc.SetFont(m_selected_font);
|
|
texty = selected_texty;
|
|
}
|
|
else
|
|
{
|
|
dc.SetFont(m_normal_font);
|
|
texty = normal_texty;
|
|
}
|
|
|
|
|
|
// create points that will make the tab outline
|
|
|
|
int clip_width = tab_width;
|
|
if (tab_x + clip_width > in_rect.x + in_rect.width)
|
|
clip_width = (in_rect.x + in_rect.width) - tab_x;
|
|
|
|
/*
|
|
wxPoint clip_points[6];
|
|
clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
|
|
clip_points[1] = wxPoint(tab_x, tab_y+2);
|
|
clip_points[2] = wxPoint(tab_x+2, tab_y);
|
|
clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
|
|
clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
|
|
clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
|
|
|
|
// FIXME: these ports don't provide wxRegion ctor from array of points
|
|
#if !defined(__WXDFB__) && !defined(__WXCOCOA__)
|
|
// set the clipping region for the tab --
|
|
wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
|
|
dc.SetClippingRegion(clipping_region);
|
|
#endif // !wxDFB && !wxCocoa
|
|
*/
|
|
// since the above code above doesn't play well with WXDFB or WXCOCOA,
|
|
// we'll just use a rectangle for the clipping region for now --
|
|
dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3);
|
|
|
|
|
|
wxPoint border_points[6];
|
|
if (m_flags &wxAUI_NB_BOTTOM)
|
|
{
|
|
border_points[0] = wxPoint(tab_x, tab_y);
|
|
border_points[1] = wxPoint(tab_x, tab_y+tab_height-6);
|
|
border_points[2] = wxPoint(tab_x+2, tab_y+tab_height-4);
|
|
border_points[3] = wxPoint(tab_x+tab_width-2, tab_y+tab_height-4);
|
|
border_points[4] = wxPoint(tab_x+tab_width, tab_y+tab_height-6);
|
|
border_points[5] = wxPoint(tab_x+tab_width, tab_y);
|
|
}
|
|
else //if (m_flags & wxAUI_NB_TOP) {}
|
|
{
|
|
border_points[0] = wxPoint(tab_x, tab_y+tab_height-4);
|
|
border_points[1] = wxPoint(tab_x, tab_y+2);
|
|
border_points[2] = wxPoint(tab_x+2, tab_y);
|
|
border_points[3] = wxPoint(tab_x+tab_width-2, tab_y);
|
|
border_points[4] = wxPoint(tab_x+tab_width, tab_y+2);
|
|
border_points[5] = wxPoint(tab_x+tab_width, tab_y+tab_height-4);
|
|
}
|
|
// else if (m_flags &wxAUI_NB_LEFT) {}
|
|
// else if (m_flags &wxAUI_NB_RIGHT) {}
|
|
|
|
int drawn_tab_yoff = border_points[1].y;
|
|
int drawn_tab_height = border_points[0].y - border_points[1].y;
|
|
|
|
|
|
if (page.active)
|
|
{
|
|
// draw active tab
|
|
|
|
// draw base background color
|
|
wxRect r(tab_x, tab_y, tab_width, tab_height);
|
|
dc.SetPen(wxPen(m_active_colour));
|
|
dc.SetBrush(wxBrush(m_active_colour));
|
|
dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4);
|
|
|
|
// this white helps fill out the gradient at the top of the tab
|
|
dc.SetPen(*wxWHITE_PEN);
|
|
dc.SetBrush(*wxWHITE_BRUSH);
|
|
dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4);
|
|
|
|
// these two points help the rounded corners appear more antialiased
|
|
dc.SetPen(wxPen(m_active_colour));
|
|
dc.DrawPoint(r.x+2, r.y+1);
|
|
dc.DrawPoint(r.x+r.width-2, r.y+1);
|
|
|
|
// set rectangle down a bit for gradient drawing
|
|
r.SetHeight(r.GetHeight()/2);
|
|
r.x += 2;
|
|
r.width -= 2;
|
|
r.y += r.height;
|
|
r.y -= 2;
|
|
|
|
// draw gradient background
|
|
wxColor top_color = *wxWHITE;
|
|
wxColor bottom_color = m_active_colour;
|
|
dc.GradientFillLinear(r, bottom_color, top_color, wxSOUTH);
|
|
}
|
|
else
|
|
{
|
|
// draw inactive tab
|
|
|
|
wxRect r(tab_x, tab_y+1, tab_width, tab_height-3);
|
|
|
|
// start the gradent up a bit and leave the inside border inset
|
|
// by a pixel for a 3D look. Only the top half of the inactive
|
|
// tab will have a slight gradient
|
|
r.x += 3;
|
|
r.y++;
|
|
r.width -= 4;
|
|
r.height /= 2;
|
|
r.height--;
|
|
|
|
// -- draw top gradient fill for glossy look
|
|
wxColor top_color = m_base_colour;
|
|
wxColor bottom_color = gdAuiStepColour(top_color, 160);
|
|
dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
|
|
|
|
r.y += r.height;
|
|
r.y--;
|
|
|
|
// -- draw bottom fill for glossy look
|
|
top_color = m_base_colour;
|
|
bottom_color = m_base_colour;
|
|
dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
|
|
}
|
|
|
|
// draw tab outline
|
|
dc.SetPen(m_border_pen);
|
|
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
|
dc.DrawPolygon(WXSIZEOF(border_points), border_points);
|
|
|
|
// there are two horizontal grey lines at the bottom of the tab control,
|
|
// this gets rid of the top one of those lines in the tab control
|
|
if (page.active)
|
|
{
|
|
if (m_flags &wxAUI_NB_BOTTOM)
|
|
dc.SetPen(wxPen(wxColour(gdAuiStepColour(m_base_colour, 170))));
|
|
// else if (m_flags &wxAUI_NB_LEFT) {}
|
|
// else if (m_flags &wxAUI_NB_RIGHT) {}
|
|
else //for wxAUI_NB_TOP
|
|
dc.SetPen(m_base_colour_pen);
|
|
|
|
//Game Develop use white pen so as to conform to white background
|
|
dc.SetPen(*wxWHITE_PEN);
|
|
|
|
dc.DrawLine(border_points[0].x+1,
|
|
border_points[0].y,
|
|
border_points[5].x,
|
|
border_points[5].y);
|
|
}
|
|
|
|
|
|
int text_offset = tab_x + 8;
|
|
int close_button_width = 0;
|
|
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
|
|
{
|
|
close_button_width = m_active_close_bmp.GetWidth();
|
|
}
|
|
|
|
int bitmap_offset = 0;
|
|
if (page.bitmap.IsOk())
|
|
{
|
|
bitmap_offset = tab_x + 8;
|
|
|
|
// draw bitmap
|
|
dc.DrawBitmap(page.bitmap,
|
|
bitmap_offset,
|
|
drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
|
|
true);
|
|
|
|
text_offset = bitmap_offset + page.bitmap.GetWidth();
|
|
text_offset += 3; // bitmap padding
|
|
|
|
}
|
|
else
|
|
{
|
|
text_offset = tab_x + 8;
|
|
}
|
|
|
|
|
|
wxString draw_text = gdAuiChopText(dc,
|
|
caption,
|
|
tab_width - (text_offset-tab_x) - close_button_width);
|
|
|
|
// draw tab text
|
|
dc.DrawText(draw_text,
|
|
text_offset,
|
|
drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1);
|
|
|
|
// draw focus rectangle
|
|
if (page.active && (wnd->FindFocus() == wnd))
|
|
{
|
|
wxRect focusRectText(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1),
|
|
selected_textx, selected_texty);
|
|
|
|
wxRect focusRect;
|
|
wxRect focusRectBitmap;
|
|
|
|
if (page.bitmap.IsOk())
|
|
focusRectBitmap = wxRect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
|
|
page.bitmap.GetWidth(), page.bitmap.GetHeight());
|
|
|
|
if (page.bitmap.IsOk() && draw_text.IsEmpty())
|
|
focusRect = focusRectBitmap;
|
|
else if (!page.bitmap.IsOk() && !draw_text.IsEmpty())
|
|
focusRect = focusRectText;
|
|
else if (page.bitmap.IsOk() && !draw_text.IsEmpty())
|
|
focusRect = focusRectText.Union(focusRectBitmap);
|
|
|
|
focusRect.Inflate(2, 2);
|
|
|
|
wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
|
|
}
|
|
|
|
// draw close button if necessary
|
|
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
|
|
{
|
|
wxBitmap bmp = m_disabled_close_bmp;
|
|
|
|
if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
|
|
close_button_state == wxAUI_BUTTON_STATE_PRESSED)
|
|
{
|
|
bmp = m_active_close_bmp;
|
|
}
|
|
|
|
wxRect rect(tab_x + tab_width - close_button_width - 1,
|
|
tab_y + (tab_height/2) - (bmp.GetHeight()/2),
|
|
close_button_width,
|
|
tab_height);
|
|
IndentPressedBitmap(&rect, close_button_state);
|
|
dc.DrawBitmap(bmp, rect.x, rect.y, true);
|
|
|
|
*out_button_rect = rect;
|
|
}
|
|
|
|
*out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
|
|
|
|
dc.DestroyClippingRegion();
|
|
}
|
|
|
|
int GDAuiTabArt::GetIndentSize()
|
|
{
|
|
return 5;
|
|
}
|
|
|
|
wxSize GDAuiTabArt::GetTabSize(wxDC& dc,
|
|
wxWindow* WXUNUSED(wnd),
|
|
const wxString& caption,
|
|
const wxBitmap& bitmap,
|
|
bool WXUNUSED(active),
|
|
int close_button_state,
|
|
int* x_extent)
|
|
{
|
|
wxCoord measured_textx, measured_texty, tmp;
|
|
|
|
dc.SetFont(m_measuring_font);
|
|
dc.GetTextExtent(caption, &measured_textx, &measured_texty);
|
|
|
|
dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty);
|
|
|
|
// add padding around the text
|
|
wxCoord tab_width = measured_textx;
|
|
wxCoord tab_height = measured_texty;
|
|
|
|
// if the close button is showing, add space for it
|
|
if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
|
|
tab_width += m_active_close_bmp.GetWidth() + 3;
|
|
|
|
// if there's a bitmap, add space for it
|
|
if (bitmap.IsOk())
|
|
{
|
|
tab_width += bitmap.GetWidth();
|
|
tab_width += 3; // right side bitmap padding
|
|
tab_height = wxMax(tab_height, bitmap.GetHeight());
|
|
}
|
|
|
|
// add padding
|
|
tab_width += 16;
|
|
tab_height += 10;
|
|
|
|
if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
|
|
{
|
|
tab_width = m_fixed_tab_width;
|
|
}
|
|
|
|
*x_extent = tab_width;
|
|
|
|
return wxSize(tab_width, tab_height);
|
|
}
|
|
|
|
|
|
void GDAuiTabArt::DrawButton(wxDC& dc,
|
|
wxWindow* WXUNUSED(wnd),
|
|
const wxRect& in_rect,
|
|
int bitmap_id,
|
|
int button_state,
|
|
int orientation,
|
|
wxRect* out_rect)
|
|
{
|
|
wxBitmap bmp;
|
|
wxRect rect;
|
|
|
|
switch (bitmap_id)
|
|
{
|
|
case wxAUI_BUTTON_CLOSE:
|
|
if (button_state & wxAUI_BUTTON_STATE_DISABLED)
|
|
bmp = m_disabled_close_bmp;
|
|
else
|
|
bmp = m_active_close_bmp;
|
|
break;
|
|
case wxAUI_BUTTON_LEFT:
|
|
if (button_state & wxAUI_BUTTON_STATE_DISABLED)
|
|
bmp = m_disabled_left_bmp;
|
|
else
|
|
bmp = m_active_left_bmp;
|
|
break;
|
|
case wxAUI_BUTTON_RIGHT:
|
|
if (button_state & wxAUI_BUTTON_STATE_DISABLED)
|
|
bmp = m_disabled_right_bmp;
|
|
else
|
|
bmp = m_active_right_bmp;
|
|
break;
|
|
case wxAUI_BUTTON_WINDOWLIST:
|
|
if (button_state & wxAUI_BUTTON_STATE_DISABLED)
|
|
bmp = m_disabled_windowlist_bmp;
|
|
else
|
|
bmp = m_active_windowlist_bmp;
|
|
break;
|
|
}
|
|
|
|
|
|
if (!bmp.IsOk())
|
|
return;
|
|
|
|
rect = in_rect;
|
|
|
|
if (orientation == wxLEFT)
|
|
{
|
|
rect.SetX(in_rect.x);
|
|
rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
|
|
rect.SetWidth(bmp.GetWidth());
|
|
rect.SetHeight(bmp.GetHeight());
|
|
}
|
|
else
|
|
{
|
|
rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
|
|
((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
|
|
bmp.GetWidth(), bmp.GetHeight());
|
|
}
|
|
|
|
IndentPressedBitmap(&rect, button_state);
|
|
dc.DrawBitmap(bmp, rect.x, rect.y, true);
|
|
|
|
*out_rect = rect;
|
|
}
|
|
|
|
int GDAuiTabArt::ShowDropDown(wxWindow* wnd,
|
|
const wxAuiNotebookPageArray& pages,
|
|
int active_idx)
|
|
{
|
|
wxMenu menuPopup;
|
|
|
|
size_t i, count = pages.GetCount();
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
const wxAuiNotebookPage& page = pages.Item(i);
|
|
wxString caption = page.caption;
|
|
|
|
// if there is no caption, make it a space. This will prevent
|
|
// an assert in the menu code.
|
|
if (caption.IsEmpty())
|
|
caption = wxT(" ");
|
|
|
|
menuPopup.AppendCheckItem(1000+i, caption);
|
|
}
|
|
|
|
if (active_idx != -1)
|
|
{
|
|
menuPopup.Check(1000+active_idx, true);
|
|
}
|
|
|
|
// find out where to put the popup menu of window items
|
|
wxPoint pt = ::wxGetMousePosition();
|
|
pt = wnd->ScreenToClient(pt);
|
|
|
|
// find out the screen coordinate at the bottom of the tab ctrl
|
|
wxRect cli_rect = wnd->GetClientRect();
|
|
pt.y = cli_rect.y + cli_rect.height;
|
|
|
|
GDAuiCommandCapture* cc = new GDAuiCommandCapture;
|
|
wnd->PushEventHandler(cc);
|
|
wnd->PopupMenu(&menuPopup, pt);
|
|
int command = cc->GetCommandId();
|
|
wnd->PopEventHandler(true);
|
|
|
|
if (command >= 1000)
|
|
return command-1000;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int GDAuiTabArt::GetBestTabCtrlSize(wxWindow* wnd,
|
|
const wxAuiNotebookPageArray& pages,
|
|
const wxSize& required_bmp_size)
|
|
{
|
|
wxClientDC dc(wnd);
|
|
dc.SetFont(m_measuring_font);
|
|
|
|
// sometimes a standard bitmap size needs to be enforced, especially
|
|
// if some tabs have bitmaps and others don't. This is important because
|
|
// it prevents the tab control from resizing when tabs are added.
|
|
wxBitmap measure_bmp;
|
|
if (required_bmp_size.IsFullySpecified())
|
|
{
|
|
measure_bmp.Create(required_bmp_size.x,
|
|
required_bmp_size.y);
|
|
}
|
|
|
|
|
|
int max_y = 0;
|
|
size_t i, page_count = pages.GetCount();
|
|
for (i = 0; i < page_count; ++i)
|
|
{
|
|
wxAuiNotebookPage& page = pages.Item(i);
|
|
|
|
wxBitmap bmp;
|
|
if (measure_bmp.IsOk())
|
|
bmp = measure_bmp;
|
|
else
|
|
bmp = page.bitmap;
|
|
|
|
// we don't use the caption text because we don't
|
|
// want tab heights to be different in the case
|
|
// of a very short piece of text on one tab and a very
|
|
// tall piece of text on another tab
|
|
int x_ext = 0;
|
|
wxSize s = GetTabSize(dc,
|
|
wnd,
|
|
wxT("ABCDEFGHIj"),
|
|
bmp,
|
|
true,
|
|
wxAUI_BUTTON_STATE_HIDDEN,
|
|
&x_ext);
|
|
|
|
max_y = wxMax(max_y, s.y);
|
|
}
|
|
|
|
return max_y+2;
|
|
}
|
|
|
|
void GDAuiTabArt::SetNormalFont(const wxFont& font)
|
|
{
|
|
m_normal_font = font;
|
|
}
|
|
|
|
void GDAuiTabArt::SetSelectedFont(const wxFont& font)
|
|
{
|
|
m_selected_font = font;
|
|
}
|
|
|
|
void GDAuiTabArt::SetMeasuringFont(const wxFont& font)
|
|
{
|
|
m_measuring_font = font;
|
|
}
|