Example #1
0
static void drawNewsSection(float x, float y, const std::vector<CUpdater::news_s>& news, size_t maxLines)
{
  float o = 624; // date text offset

  for(size_t i=0; i<news.size() && i < maxLines; i++) 
  {
    // news date
    //g_font2->PrintF(x+o, y, r3dColor(243, 182, 86), news[i].date_.c_str());

    // news text
	const char* newsText = news[i].name_.c_str();
    SIZE ts = GetTextExtent(g_font2, newsText);
    r3dRECT r = {x, y, 785, 25};
    r3dColor clr = r3dColor(255, 255, 255);
    
    // selection and underline
    if(insideRect(r, g_mx, g_my)) {
      clr = r3dColor(255, 216, 0);
      //r3dDrawBox2D(x, y + (float)ts.cy, (float)ts.cx, 1, clr);
      if(g_mb) {
        ShellExecute(NULL, "open", news[i].url_.c_str(), "", NULL, SW_SHOW);
      }
    }

    g_font2->DrawText(x, y, 785, 25, clr, newsText, D3DFONT_CENTERED);
    y += 25;
  }
  
  //TODO: "View All"

  return;  
}
int PathBubble0::whichTerm( QPointF pos)
{	   
	float x=pos.x(), y=pos.y();	
	for(int i=0; i<XL.size(); i++)
	{
		if(insideRect(x, y, XL[i], YB[i], XR[i], YT[i]))
		{
			return i;
		}
	}
	return -1;
}
Example #3
0
void handleMouseUp(const SDL_MouseButtonEvent &event,
                   std::vector<GuiButton *> buttons)
{
    if (event.button != SDL_BUTTON_LEFT) {
        return;
    }

    for (auto &b : buttons) {
        if (insideRect(event.x, event.y, b->getDisplayArea())) {
            b->click();
        }
    }
}
Example #4
0
static void drawCloseButton()
{
  static r3dRECT g_rCloseBtn = {732, 0, 50, 50};

  // close button
  r3dColor clr(255, 255, 255);
  if(insideRect(g_rCloseBtn, g_mx, g_my)) {
    g_imBtnClose->draw(732, 0, 64, 64, clr);
    if(g_mb) {
      g_bExit = true;
    }
  }
}
Example #5
0
static bool drawUrl(float x, float y, const char* msg)
{
    CD3DFont* fnt = g_font1;
    // news text
    SIZE ts = GetTextExtent(fnt, msg);
    r3dRECT r = {x, y, (float)ts.cx, (float)ts.cy};
    r3dColor clr = r3dColor(105, 105, 105);
    
    // selection and underline
    if(insideRect(r, g_mx, g_my)) {
      clr = r3dColor(255, 255, 255);
      r3dDrawBox2D(x, y + (float)ts.cy, (float)ts.cx, 1, clr);
      if(g_mb) {
        return true;
      }
    }

    fnt->PrintF(x, y, clr, "%s", msg);
    return false;
}
Example #6
0
static void drawLoginButtons(CUpdater& updater)
{
  static r3dRECT g_rLoginBtn  = {237, 480, 106, 46};
  static r3dRECT g_rRegisterNewBtn = {348, 480, 256, 64};
  static r3dRECT g_rLoginEdit = {250, 335, 424, 24};
  static r3dRECT g_rPwdEdit   = {250, 420, 424, 24};
  r3dColor clr(255, 255, 255);
  
  // if login or update in process, draw only needed things
  bool testDraw = (GetAsyncKeyState(VK_F1) & 0x8000) && false;
  if(testDraw || updater.gUserProfile.loginAnswerCode == CLoginHelper::ANS_Processing 
     || updater.gUserProfile.loginAnswerCode == CLoginHelper::ANS_Logged)
  {
    //r3dDrawBox2D(g_rLoginEdit.left-2, g_rLoginEdit.top-2, g_rLoginEdit.width+4, g_rLoginEdit.height+4, r3dColor(0, 0, 0, 100));
    //r3dDrawBox2D(g_rPwdEdit.left-2, g_rPwdEdit.top-2, g_rPwdEdit.width+4, g_rPwdEdit.height+4, r3dColor(0, 0, 0, 100));
    editTextField(g_rLoginEdit.left, g_rLoginEdit.top, updater.gUserProfile.username, false, 0);
    editTextField(g_rPwdEdit.left, g_rPwdEdit.top, updater.gUserProfile.passwd, false, 1);

    if(updater.gUserProfile.loginAnswerCode == CLoginHelper::ANS_Logged) {
      updater.SwitchToUpdater();
    }

    return;
  }
  
  // login button. enabled if we have all data
  if(*updater.gUserProfile.username && *updater.gUserProfile.passwd && insideRect(g_rLoginBtn, g_mx, g_my)) {
    g_imBtnLogin->draw(237, 480, 128, 64, clr);
    if(g_mb) {
      updater.DoLogin();
    }
  }

  if(drawUrl(235, 540, "Forgot Password ?")) {
    ShellExecute(NULL, "open", gLauncherConfig.accountForgotPasswordURL.c_str(), "", NULL, SW_SHOW);
  }

  // register new account button
  if(insideRect(g_rRegisterNewBtn, g_mx, g_my)) 
  {
    g_imBtnRegisterNew->draw(348, 480, 256, 64, clr);
    if(g_mb) {
      /*if(eulaShowDialog(0) != IDOK) {
        return;
      }
      if(eulaShowDialog(1) != IDOK) {
        return;
      }
    */
	 // updater.status_ = CUpdater::STATUS_NeedRegister;
  //MessageBox(NULL, "Register at Godanel LuFy", "Allright Register Account", MB_OK);
		//ShellExecute(NULL, "open", gLauncherConfig.accountRegisterURL.c_str(), "", NULL, SW_SHOW);
		ShellExecute(NULL, "open", gLauncherConfig.accountRegisterURL.c_str(), "", NULL, SW_SHOW);
    }
  }
  
  // login error
  if(updater.loginErrMsg_[0]) {
    static float bx = 230;
    static float by = 260;
    //r3dDrawBox2D(bx, by, 331, 25, r3dColor(0, 0, 0, 150));
    g_font1->DrawText(bx, by, 331, 25, r3dColor(130, 130, 130), updater.loginErrMsg_, D3DFONT_CENTERED);
  }
  
  // name/pwd logic
  static int focusId = updater.gUserProfile.username[0] ? 1 : 0;
  
  if(g_mb && insideRect(g_rLoginEdit, g_mx, g_my)) {
    focusId = 0;
    win32_input_Flush();
  }
  if(g_mb && insideRect(g_rPwdEdit, g_mx, g_my)) {
    focusId = 1;
    win32_input_Flush();
  }

  int key;
  key = editTextField(g_rLoginEdit.left, g_rLoginEdit.top, updater.gUserProfile.username, focusId == 0, 0, 64);
  if(key == 9)  focusId = 1;
  if(key == 13 && updater.gUserProfile.username[0]) focusId = 1;

  key = editTextField(g_rPwdEdit.left, g_rPwdEdit.top, updater.gUserProfile.passwd, focusId == 1, 1);
  if(key == 9)  focusId = 0;
  if(key == 13 && updater.gUserProfile.passwd[0] && updater.gUserProfile.username[0])
    updater.DoLogin();
    
  return;
}
Example #7
0
static void drawSerialCheckButtons(CUpdater& updater)
{
  static r3dRECT g_rValidateBtn   = {164, 402, 456, 77};
  static r3dRECT g_rGetSerialBtn  = {164, 546, 456, 77};
  static r3dRECT g_rEditFields[2] = {
    {182, 349, 424, 24},
  };
  // email, serial
  static char gEditText[1][512] = {0};
  static int gInputLen[1] = {48};
  
  r3dColor clr(255, 255, 255);
  
  // if serial check in process, draw only needed things
  bool testDraw = (GetAsyncKeyState(VK_F1) & 0x8000) && false;
  if(testDraw || updater.checkSerialHelper.processCode == CCheckSerialHelper::CA_Processing) 
  {
    for(int i=0; i<2; i++) {
      r3dDrawBox2D(g_rEditFields[i].left-2, g_rEditFields[i].top-2, g_rEditFields[i].width+4, g_rEditFields[i].height+4, r3dColor(0, 0, 0, 100));
      editTextField(g_rEditFields[i].left, g_rEditFields[i].top, gEditText[i], false, 0);
    }
    return;
  }
  
  // register button. enabled if we have all data
  if(gEditText[0][0] && insideRect(g_rValidateBtn, g_mx, g_my)) 
  {
    g_imBtnValidate->draw(g_rValidateBtn.left, g_rValidateBtn.top, g_rValidateBtn.width, g_rValidateBtn.height, clr);
    if(g_mb) 
    {
      strcpy(updater.checkSerialHelper.serial, gEditText[0]);
      updater.DoCheckSerial();
    }
  }
  
  // some temp warning
  {
    r3dColor clr(251, 1, 2, 160);
    g_font1->PrintF(317, 325, clr, "You can paste (Control-V) your serial");
    //g_font1->PrintF(180, 374, clr, "Make sure not to confuse O and 0 (zero), I and 1 (one)");
  }
  
  // get new serial button
  if(insideRect(g_rGetSerialBtn, g_mx, g_my)) 
  {
    g_imBtnGetSerial->draw(g_rGetSerialBtn.left, g_rGetSerialBtn.top, g_rGetSerialBtn.width, g_rGetSerialBtn.height, clr);
    if(g_mb) 
    {
		ShellExecute(NULL, "open", gLauncherConfig.serialBuyURL.c_str(), "", NULL, SW_SHOW);
    }
  }
  
  // input fields logic
  static int focusId = 0;
  
  for(int i=0; i<1; i++) 
  {
    if(g_mb && insideRect(g_rEditFields[i], g_mx, g_my)) {
      focusId = i;
      win32_input_Flush();
    }
    
    int key;
    key = editTextField(
      g_rEditFields[i].left, 
      g_rEditFields[i].top, 
      gEditText[i], 
      focusId == i, 
      0,
      gInputLen[i]);
      
    //if(key == 9)  focusId = (GetKeyState(VK_SHIFT)&0x8000) ? focusId-1 : focusId+1;
    //if(key == 13 && gEditText[i][0]) focusId++;
    //if(focusId >= 2) focusId = 0;
    //if(focusId <  0) focusId = 1;
  }
  
  strupr(gEditText[1]);

  return;
}
Example #8
0
static void drawTimeExpiredButtons(CUpdater& updater)
{
  static r3dRECT g_rGetNewKeyBtn   = {165, 343, 455, 72};
  static r3dRECT g_rApplyNewKeyBtn = {165, 550, 455, 72};
  static r3dRECT g_rEditFields[1] = {
    {182, 497, 424, 24},
  };
  // email, passwd1, passwd2, serial
  static char gEditText[1][512] = {0};
  static int gInputLen[1] = {64};

  r3dColor clr(255, 255, 255);

  // if login in process, draw only needed things
  bool testDraw = (GetAsyncKeyState(VK_F1) & 0x8000) && false;
  if(testDraw || updater.createAccHelper.createAccCode == CCreateAccHelper::CA_Processing) 
  {
    for(int i=0; i<1; i++) {
      r3dDrawBox2D(g_rEditFields[i].left-2, g_rEditFields[i].top-2, g_rEditFields[i].width+4, g_rEditFields[i].height+4, r3dColor(0, 0, 0, 100));
      editTextField(g_rEditFields[i].left, g_rEditFields[i].top, gEditText[i], false, i>=1 ? 1 : 0);
    }
    return;
  }
  
  // apply new key button. enabled if we have all data
  if(gEditText[0][0] && insideRect(g_rApplyNewKeyBtn, g_mx, g_my)) 
  {
    g_imBtnApplyNewKey->draw(g_rApplyNewKeyBtn.left, g_rApplyNewKeyBtn.top, g_rApplyNewKeyBtn.width, g_rApplyNewKeyBtn.height, clr);
    if(g_mb) 
    {
      updater.DoApplyNewKey(gEditText[0]);
      return;
    }
  }

  // get new serial button
  if(insideRect(g_rGetNewKeyBtn, g_mx, g_my)) 
  {
    g_imBtnGetNewKey->draw(g_rGetNewKeyBtn.left, g_rGetNewKeyBtn.top, g_rGetNewKeyBtn.width, g_rGetNewKeyBtn.height, clr);
    if(g_mb) 
    {
      ShellExecute(NULL, "open", gLauncherConfig.serialExpiredBuyURL.c_str(), "", NULL, SW_SHOW);
    }
  }
  
  // input fields logic
  static int focusId = 0;
  
  for(int i=0; i<1; i++) 
  {
    if(g_mb && insideRect(g_rEditFields[i], g_mx, g_my)) {
      focusId = i;
      win32_input_Flush();
    }
    
    int key;
    key = editTextField(
      g_rEditFields[i].left, 
      g_rEditFields[i].top, 
      gEditText[i], 
      focusId == i, 
      0,
      gInputLen[i]);
  }
  
  return;
}
Example #9
0
static void drawRegisterButtons(CUpdater& updater)
{
  static r3dRECT g_rRegisterBtn  = {254, 531, 276, 90};
  static r3dRECT g_rEditFields[3] = {
    {182, 351, 424, 24},
    {182, 411, 424, 24},
    {182, 472, 424, 24},
  };
  // email, passwd1, passwd2, serial
  static char gEditText[3][512] = {0};
  static int gInputLen[3] = {64, 32, 32};

  r3dColor clr(255, 255, 255);

  // if login in process, draw only needed things
  bool testDraw = (GetAsyncKeyState(VK_F1) & 0x8000) && false;
  if(testDraw || updater.createAccHelper.createAccCode == CCreateAccHelper::CA_Processing) 
  {
    for(int i=0; i<3; i++) {
      r3dDrawBox2D(g_rEditFields[i].left-2, g_rEditFields[i].top-2, g_rEditFields[i].width+4, g_rEditFields[i].height+4, r3dColor(0, 0, 0, 100));
      editTextField(g_rEditFields[i].left, g_rEditFields[i].top, gEditText[i], false, i>=1 ? 1 : 0);
    }
    return;
  }
  
  // register button. enabled if we have all data
  if(gEditText[0][0] && gEditText[1][0] && gEditText[2][0] &&
     insideRect(g_rRegisterBtn, g_mx, g_my)) 
  {
    g_imBtnRegister->draw(g_rRegisterBtn.left, g_rRegisterBtn.top, g_rRegisterBtn.width, g_rRegisterBtn.height, clr);
    if(g_mb) 
    {
      strcpy(updater.createAccHelper.username, gEditText[0]);
      strcpy(updater.createAccHelper.passwd1,  gEditText[1]);
      strcpy(updater.createAccHelper.passwd2,  gEditText[2]);
      strcpy(updater.createAccHelper.serial,   updater.checkSerialHelper.serial);
      updater.DoCreateAccount();
    }
  }
  
  // input fields logic
  static int focusId = 0;
  
  for(int i=0; i<3; i++) 
  {
    if(g_mb && insideRect(g_rEditFields[i], g_mx, g_my)) {
      focusId = i;
      win32_input_Flush();
    }
    
    int key;
    key = editTextField(
      g_rEditFields[i].left, 
      g_rEditFields[i].top, 
      gEditText[i], 
      focusId == i, 
      (i == 1 || i == 2) ? 1 : 0,
      gInputLen[i]);
    if(key == 9)  focusId = (GetKeyState(VK_SHIFT)&0x8000) ? focusId-1 : focusId+1;
    if(key == 13 && gEditText[i][0]) focusId++;
    
    if(focusId >= 3) focusId = 0;
    if(focusId <  0) focusId = 2;
  }
  
  return;
}
Example #10
0
static void drawUpdateButtons(CUpdater& updater)
{
  static r3dRECT g_rPlayBtn  = {291, 482, 214, 69};
  static r3dRECT g_rTopBtn[6] = {
    {143, 182, 179, 56},
    {353, 182, 127, 56},
    {514, 182,  138, 56},
    {708, 38,  22, 20},
    {660, 38,  22, 20},
    {684, 38,  22, 20}
  };
    

  r3dColor clr = r3dColor(255, 255, 255);

  // play button. active only when updater finished updating.
  // and servers logically offline
  if(updater.result_ == CUpdater::RES_PLAY && updater.IsServerOnline())
  {
    if(insideRect(g_rPlayBtn, g_mx, g_my)) {
      g_imBtnPg[1]->draw(291, 482, 256, 128, clr);
    } else {
      g_imBtnPg[0]->draw(291, 482, 256, 128, clr);
    }

    if(insideRect(g_rPlayBtn, g_mx, g_my) && g_mb) 
    {
      if(updater.CheckForNewData())
      {
        MessageBox(NULL, "There is new build available, please log in again", "Update required", MB_OK | MB_ICONEXCLAMATION);
        g_bExit = true;
        return;
      }
      g_bStartGame = true;
    }
  }
  
  // top menu buttons
  for(int btnIdx=0; btnIdx<6; btnIdx++)
  {
    if(insideRect(g_rTopBtn[btnIdx], g_mx, g_my)) 
    {
		if(btnIdx == 0)
			g_imBtnTopMenu[btnIdx]->draw(143, 182, 256, 64,clr);
		else if(btnIdx == 1)
			g_imBtnTopMenu[btnIdx]->draw(353, 182, 128, 64,clr);
		else if(btnIdx == 2)
			g_imBtnTopMenu[btnIdx]->draw(506, 182, 256, 64,clr);
		else if(btnIdx == 3)
			g_imBtnTopMenu[btnIdx]->draw(708, 37, 32, 32,clr);
		else if(btnIdx == 4)
			g_imBtnTopMenu[btnIdx]->draw(659, 37, 32, 32,clr);
		else if(btnIdx == 5)
			g_imBtnTopMenu[btnIdx]->draw(684, 37, 32, 32,clr);
		else
			g_imBtnTopMenu[btnIdx]->draw(g_rTopBtn[btnIdx].left, g_rTopBtn[btnIdx].top, g_rTopBtn[btnIdx].width, g_rTopBtn[btnIdx].height, clr);
        
      if(g_mb) {
        executeTopMenuButton(updater, btnIdx);
      }
    }
  }
  
  return;
}
void clAuiGlossyTabArt::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)
{
    wxColour bgColour = wxColour(EditorConfigST::Get()->GetCurrentOutputviewBgColour());
    wxColour penColour;
    wxColour textColour;
    bool isBgColourDark = DrawingUtils::IsDark(bgColour);
    if ( isBgColourDark ) {
        penColour = DrawingUtils::LightColour(bgColour, 4.0);
    } else {
        bgColour = *wxWHITE;
        penColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW);
    }
    textColour = EditorConfigST::Get()->GetCurrentOutputviewFgColour();
    int curx = 0;
    
    // Allow the plugins to override the default colours
    clColourEvent colourEvent( wxEVT_COLOUR_TAB );
    colourEvent.SetIsActiveTab( page.active );
    colourEvent.SetPage( page.window );
    if ( EventNotifier::Get()->ProcessEvent( colourEvent ) ) {
        bgColour = colourEvent.GetBgColour();
        textColour = colourEvent.GetFgColour();
    }
    
    // Allow the plugins to override the border colour
    wxColour originalPenColour = penColour;
    clColourEvent borderColourEvent( wxEVT_GET_TAB_BORDER_COLOUR );
    if ( EventNotifier::Get()->ProcessEvent( borderColourEvent ) ) {
        penColour = borderColourEvent.GetBorderColour();
    }
    
    wxGCDC gdc;
    if ( !DrawingUtils::GetGCDC(dc, gdc) )
        return;
    
    m_penColour = penColour;
    
    wxGraphicsPath path = gdc.GetGraphicsContext()->CreatePath();
    gdc.SetPen( penColour );
    
    wxSize sz = GetTabSize(gdc, wnd, page.caption, page.bitmap, page.active, close_button_state, x_extent);
    
    wxRect rr (in_rect.GetTopLeft(), sz);
    rr.y += TAB_Y_OFFSET;
    rr.width -= 1;

#ifndef __WXMAC__
    if ( page.active ) {
        rr.y -= 2;
        rr.height += 2;
    }
#endif

#ifdef __WXGTK__
    rr.height += TAB_HEIGHT_SPACER;
#else
    rr.height += 4;
#endif

    /// the tab start position (x)
    curx = rr.x + 7;
    
    // Set clipping region
    int clip_width = rr.width;
    if (rr.x + clip_width > in_rect.x + in_rect.width)
        clip_width = (in_rect.x + in_rect.width) - rr.x;
    
    // 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 --
    gdc.SetClippingRegion(rr.x, rr.y, clip_width, rr.height);
    gdc.SetBrush( bgColour );
    gdc.SetPen( penColour );
    
    if ( page.active ) {
        path.AddRoundedRectangle(rr.x, rr.y, rr.width-1, rr.height, 6.5);
        gdc.GetGraphicsContext()->FillPath( path );
        gdc.GetGraphicsContext()->StrokePath( path );
        
    } else {
        if ( !m_bgColour.IsOk() ) {
            wxColour b, p;
            DoGetTabAreaBackgroundColour(b, p);
            m_bgColour = b;
        }
        DoDrawInactiveTabSeparator(gdc, rr);
    }
    
    if ( !page.active ) {
        // Draw a line at the bottom rect
        gdc.SetPen(penColour);
        gdc.DrawLine(in_rect.GetBottomLeft(), in_rect.GetBottomRight());
        
    }
    
    wxString caption = page.caption;
    if ( caption.IsEmpty() ) {
        caption = "Tp";
    }
    
    wxFont fnt = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    if ( page.active ) {
        fnt.SetWeight(wxFONTWEIGHT_BOLD);
    }
    gdc.SetFont( fnt );
    wxSize ext = gdc.GetTextExtent( caption );
    if ( caption == "Tp" )
        caption.Clear();
    
    /// Draw the bitmap
    if ( page.bitmap.IsOk() ) {
        int bmpy = (rr.y + (rr.height - page.bitmap.GetHeight())/2)-TAB_Y_OFFSET;
        gdc.GetGraphicsContext()->DrawBitmap( page.bitmap, curx, bmpy, page.bitmap.GetWidth(), page.bitmap.GetHeight());
        curx += page.bitmap.GetWidth();
        curx += 3;
    }
    
    /// Draw the text
    gdc.SetTextForeground( textColour );
    gdc.GetGraphicsContext()->DrawText( page.caption, curx, (rr.y + (rr.height - ext.y)/2)-TAB_Y_OFFSET+TEXT_Y_SPACER);
    
    // advance the X offset
    curx += ext.x;
    curx += 3;
    
    /// Draw the X button on the tab
    if ( close_button_state != wxAUI_BUTTON_STATE_HIDDEN ) {
        int btny = (rr.y + (rr.height/2))-TAB_Y_OFFSET+TEXT_Y_SPACER;
        if ( close_button_state == wxAUI_BUTTON_STATE_PRESSED ) {
            curx += 1;
            btny += 1;
        }
        
        /// Defines the rectangle surrounding the X button
        wxRect xRect = wxRect(curx, btny - X_RADIUS, X_DIAMETER, X_DIAMETER);
        *out_button_rect = xRect;
        
        /// Defines the 'x' inside the circle
        wxPoint circleCenter( curx + X_RADIUS, btny);
        wxDouble xx_width = ::sqrt( ::pow(X_DIAMETER, 2.0) /2.0 );
        wxDouble x_square = (circleCenter.x - (xx_width/2.0));
        wxDouble y_square = (circleCenter.y - (xx_width/2.0));
        
        wxPoint2DDouble ptXTopLeft(x_square, y_square);
        wxRect2DDouble insideRect(ptXTopLeft.m_x, ptXTopLeft.m_y, xx_width, xx_width);
        insideRect.Inset(1.0 , 1.0); // Shrink it by 1 pixle
        
        /// Draw the 'x' itself
        wxGraphicsPath xpath = gdc.GetGraphicsContext()->CreatePath();
        xpath.MoveToPoint( insideRect.GetLeftTop() );
        xpath.AddLineToPoint( insideRect.GetRightBottom());
        xpath.MoveToPoint( insideRect.GetRightTop() );
        xpath.AddLineToPoint( insideRect.GetLeftBottom() );
        gdc.SetPen( wxPen(textColour, 1) );
        gdc.GetGraphicsContext()->StrokePath( xpath  );
        
        curx += X_DIAMETER;
    }
    *out_tab_rect = rr;
    gdc.DestroyClippingRegion();
}
void clAuiMainNotebookTabArt::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)
{
    int curx = 0;
    wxGCDC gdc;
    if(!DrawingUtils::GetGCDC(dc, gdc)) return;
    
    wxColour penColour = page.active ? m_activeTabPenColour : m_penColour;
    wxGraphicsPath path = gdc.GetGraphicsContext()->CreatePath();
    gdc.SetPen(penColour);

    wxSize sz = GetTabSize(gdc, wnd, page.caption, page.bitmap, page.active, close_button_state, x_extent);

    wxRect rr(in_rect.GetTopLeft(), sz);
    rr.y += TAB_Y_OFFSET;
    rr.width -= 1;

#ifndef __WXMAC__
    if(page.active) {
        rr.y -= 2;
        rr.height += 2;
    }
#endif

#ifdef __WXGTK__
    rr.height += TAB_HEIGHT_SPACER;
#else
    rr.height += 4;
#endif

    /// the tab start position (x)
    curx = rr.x + 7;

    // Set clipping region
    int clip_width = rr.width;
    if(rr.x + clip_width > in_rect.x + in_rect.width) clip_width = (in_rect.x + in_rect.width) - rr.x;

    gdc.SetClippingRegion(rr.x, rr.y, clip_width, rr.height);
    gdc.SetBrush(m_bgColour);
    gdc.SetPen(penColour);

    if(page.active) {
        gdc.SetBrush(m_activeTabBgColour);
        path.AddRoundedRectangle(rr.x, rr.y, rr.width - 1, rr.height, TAB_RADIUS);
        gdc.GetGraphicsContext()->FillPath(path);
        gdc.GetGraphicsContext()->StrokePath(path);

    } else {
        wxGraphicsPath outerPath = gdc.GetGraphicsContext()->CreatePath();
        gdc.SetPen(penColour);
        outerPath.AddRoundedRectangle(rr.x, rr.y, rr.width - 1, rr.height, TAB_RADIUS);
        gdc.GetGraphicsContext()->StrokePath(outerPath);

        gdc.SetPen(m_innerPenColour);
        path.AddRoundedRectangle(rr.x + 1, rr.y + 1, rr.width - 3, rr.height - 1, TAB_RADIUS);
        gdc.GetGraphicsContext()->StrokePath(path);

        gdc.SetBrush(m_tabBgColour);
        gdc.GetGraphicsContext()->StrokePath(path);
        gdc.GetGraphicsContext()->FillPath(path);
        gdc.SetPen(penColour);
    }

    if(!page.active) {
        // Draw a line at the bottom rect
        gdc.SetPen(m_activeTabPenColour);
        gdc.DrawLine(in_rect.GetBottomLeft(), in_rect.GetBottomRight());
    }

    wxString caption = page.caption;
    if(caption.IsEmpty()) {
        caption = "Tp";
    }

    wxFont fnt = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    if(page.active) {
        fnt.SetWeight(wxFONTWEIGHT_BOLD);
    }
    gdc.SetFont(fnt);
    wxSize ext = gdc.GetTextExtent(caption);
    if(caption == "Tp") caption.Clear();

    /// Draw the bitmap
    if(page.bitmap.IsOk()) {
        int bmpy = (rr.y + (rr.height - page.bitmap.GetHeight()) / 2) - TAB_Y_OFFSET;
        gdc.GetGraphicsContext()->DrawBitmap(page.bitmap, curx, bmpy, page.bitmap.GetWidth(), page.bitmap.GetHeight());
        curx += page.bitmap.GetWidth();
        curx += 3;
    }

    /// Draw the text
    wxColour textColour = page.active ? m_activeTabTextColour : m_tabTextColour;
    gdc.SetTextForeground(textColour);
    gdc.GetGraphicsContext()->DrawText(
        page.caption, curx, (rr.y + (rr.height - ext.y) / 2) - TAB_Y_OFFSET + TEXT_Y_SPACER);

    // advance the X offset
    curx += ext.x;
    curx += 3;

    /// Draw the X button on the tab
    if(close_button_state != wxAUI_BUTTON_STATE_HIDDEN) {
        int btny = (rr.y + (rr.height / 2)) - TAB_Y_OFFSET + TEXT_Y_SPACER;
        if(close_button_state == wxAUI_BUTTON_STATE_PRESSED) {
            curx += 1;
            btny += 1;
        }

        /// Defines the rectangle surrounding the X button
        wxRect xRect = wxRect(curx, btny - X_RADIUS, X_DIAMETER, X_DIAMETER);
        *out_button_rect = xRect;

        /// Defines the 'x' inside the circle
        wxPoint circleCenter(curx + X_RADIUS, btny);
        wxDouble xx_width = ::sqrt(::pow(X_DIAMETER, 2.0) / 2.0);
        wxDouble x_square = (circleCenter.x - (xx_width / 2.0));
        wxDouble y_square = (circleCenter.y - (xx_width / 2.0));

        wxPoint2DDouble ptXTopLeft(x_square, y_square);
        wxRect2DDouble insideRect(ptXTopLeft.m_x, ptXTopLeft.m_y, xx_width, xx_width);
        insideRect.Inset(1.0, 1.0); // Shrink it by 1 pixle

        /// Draw the 'x' itself
        wxGraphicsPath xpath = gdc.GetGraphicsContext()->CreatePath();
        xpath.MoveToPoint(insideRect.GetLeftTop());
        xpath.AddLineToPoint(insideRect.GetRightBottom());
        xpath.MoveToPoint(insideRect.GetRightTop());
        xpath.AddLineToPoint(insideRect.GetLeftBottom());
        gdc.SetPen(wxPen(textColour, 1));
        gdc.GetGraphicsContext()->StrokePath(xpath);

        curx += X_DIAMETER;
    }
    *out_tab_rect = rr;
    gdc.DestroyClippingRegion();
}