//------------------------------------------------------------------------------ // gso_Button class -- // (C) Piero Giubilato 2008-2010, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "gso_Button.cpp" // [Author] "Piero Giubilato" // [Version] "1.3" // [Modified by] "Piero Giubilato" // [Last revision] "20 Apr 2009" // [Language] "C++" // [Compiler] "Visual C++ 9.x" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "Source for the gso_Button class" // [Key documentation] // "Visual C++ Reference Help" // "Root reference guide" // {Trace} //______________________________________________________________________________ // Standard component #include // Root component #include // Application component #include "global.h" #include "gso_Shaper.h" #include "gso_Button.h" // CINT Preprocessor class import definition ClassImp(gso_Button) //______________________________________________________________________________ const TGFont* gso_Button::font_Default = 0; //______________________________________________________________________________ gso_Button::gso_Button(const TGWindow* window, const char* text, UInt_t width, UInt_t height, UInt_t mode, UInt_t textColor, UInt_t foreColor, UInt_t backColor, Float_t bvlRadius, Float_t bvlFlatness) :gso_Frame(window, width, height, 0, 1, backColor, backColor) { // Default constructor dbg_Print("gso_Button::gso_Button:(default)", DBG_LVL_ZERO); // Button mode btn_Mode = mode; // Default button colors btn_textColor = textColor; // Text color btn_foreColor = foreColor; // Fore color btn_backColor = backColor; // Back color // Default button shape parameters btn_Overlap = 0; // Button/Bevel overlap btn_Radius = bvlRadius; // Corners radius (7-9 looks good) btn_Flatness = bvlFlatness; // Vertical scale factor btn_Depressed = -0.5; // Pressed vertical factor // Default led shape parameters led_Flatness = 0.5; // Vertical scale factor // Label label_Text.Form(text); btn_Label = 0; // Status btn_Inside = false; btn_Down = false; // Initialize the button! Init(); } //______________________________________________________________________________ gso_Button::~gso_Button() { // Default destructor dbg_Print("gso_Button::~gso_Button:()", DBG_LVL_ZERO); // Removes the old PixMap from the graphic server for (UInt_t i = 0; i < 5; i++) { if (frame_PxMap[i]) gVirtualX->DeletePixmap(frame_PxMap[i]); } } //______________________________________________________________________________ void gso_Button::Init() { // Default destructor dbg_Print("gso_Button::Init:()", DBG_LVL_MAKE); // The default GC for text drawing norm_gc_Hnd = (*gClient->GetResourcePool()->GetFrameGC())(); // Enables the events handler AddInput(kButtonPressMask | kButtonReleaseMask); AddInput(kEnterWindowMask | kLeaveWindowMask); Connect("ProcessedEvent(Event_t*)", "gso_Button", this, "Event(Event_t*)"); // Creates the font UInt_t fWidth = 0, fHeight = 0; font_Default = gClient->GetResourcePool()->GetDefaultFont(); font_Struct = font_Default->GetFontStruct(); TGFont* font = fClient->GetFontPool()->FindFont(font_Struct); if (!font) { font = fClient->GetFontPool()->GetFont(font_Default); font_Struct = font->GetFontStruct(); } // Creates the label label_WrapLength = -1; btn_Label = new TGHotString(label_Text.Data()); if (btn_Label->GetLength()) { label_Layout = font->ComputeTextLayout(btn_Label->GetString(), btn_Label->GetLength(), label_WrapLength, kTextLeft, 0, &label_Width, &label_Height); } else label_Layout = 0; // Set font default color and name SetTextColor(btn_textColor); SetFont("Calibri", false); // Clears the pixmap references for (UInt_t i = 0; i < 5; i++) frame_PxMap[i] = 0; // Draw the button for the first time Draw(); } //______________________________________________________________________________ void gso_Button::draw_Push(UChar_t** chr_Map) { // Creates the object dbg_Print("gso_Button::draw_Push:(default)", DBG_LVL_STEP); // Pivot vars UInt_t width = ClrWidth() + btn_Overlap * 2; UInt_t height = ClrHeight() + btn_Overlap * 2; // Necessary pivot maps Float_t* surf_Map[2]; for (int i = 0; i < 2; i++) surf_Map[i] = new Float_t[(width + 1) * (height + 1)]; UChar_t* surf_Mask[2]; for (int i = 0; i < 2; i++) surf_Mask[i] = new UChar_t[width * height]; UChar_t* col_Map[5]; for (int i = 0; i < 5; i++) col_Map[i] = new UChar_t[width * height * 4]; // Creates the button Up/Down maps + mask gso_Shaper::shape_Button(surf_Map[0], surf_Mask[0], width, height, btn_Radius, btn_Flatness); gso_Shaper::shape_scale_Z(surf_Map[1], surf_Map[0], width, height, btn_Depressed); switch (btn_Mode) { case km_Button: gso_Shaper::shape_scale_Z(surf_Map[1], surf_Map[0], width, height, btn_Depressed); break; case km_Latch: gso_Shaper::shape_scale_Z(surf_Map[1], surf_Map[0], width, height, btn_Depressed ); break; } // Derives the border mask as inverse of the surf mask gso_Shaper::mask_Invert(surf_Mask[1], surf_Mask[0], width, height); // Sets the material for the button gso_Material mat(gso_Renderer::k_Material); mat.k_Color = btn_foreColor; // Renders the surface UP/Off map gso_Renderer::l_Strenght(gso_Renderer::kl_Default); gso_Shaper::shape_Render(col_Map[0], surf_Map[0], surf_Mask[0], width, height, &mat, btn_backColor); // Renders the surface DOWN/Off map (used only in latch mode) if (btn_Mode == km_Latch) { gso_Renderer::l_Strenght(gso_Renderer::kl_Default + 0.2); gso_Shaper::shape_Render(col_Map[4], surf_Map[1], surf_Mask[0], width, height, &mat, btn_backColor); } // Renders the surface DOWN/On map gso_Renderer::l_Strenght(gso_Renderer::kl_Default + 0.4); gso_Shaper::shape_Render(col_Map[1], surf_Map[1], surf_Mask[0], width, height, &mat, btn_backColor); // Renders the surface OVER (UP On) map gso_Shaper::shape_Render(col_Map[2], surf_Map[0], surf_Mask[0], width, height, &mat, btn_backColor); // Create a flat equal to the desktop UInt_t px_Color = 0; gso_Shaper::map_Pixel(&px_Color, btn_backColor); gso_Shaper::map_Flat(col_Map[3], width, height, px_Color); // Generate the final maps! gso_Shaper::map_Sum(chr_Map[0], col_Map[0], surf_Mask[0], col_Map[3], surf_Mask[1], width, height, 1); gso_Shaper::map_Sum(chr_Map[1], col_Map[1], surf_Mask[0], col_Map[3], surf_Mask[1], width, height, 1); gso_Shaper::map_Sum(chr_Map[2], col_Map[2], surf_Mask[0], col_Map[3], surf_Mask[1], width, height, 1); if (btn_Mode == km_Latch) { gso_Shaper::map_Sum(chr_Map[3], col_Map[4], surf_Mask[0], col_Map[3], surf_Mask[1], width, height, 1); } // Kills the pivot maps for (UInt_t i = 0; i < 2; i++) delete[] surf_Map[i]; for (UInt_t i = 0; i < 2; i++) delete[] surf_Mask[i]; for (UInt_t i = 0; i < 5; i++) delete[] col_Map[i]; } //______________________________________________________________________________ void gso_Button::draw_Latch(UChar_t** chr_Map) { // Creates the object dbg_Print("gso_Button::draw_Latch:(default)", DBG_LVL_STEP); // Uses the same maps as the push button draw_Push(chr_Map); } //______________________________________________________________________________ void gso_Button::draw_Led(UChar_t** chr_Map) { // Creates the object dbg_Print("gso_Button::draw_Led:(default)", DBG_LVL_STEP); // Pivot vars UInt_t width = ClrWidth(); UInt_t height = ClrHeight(); UInt_t size; (width >= height) ? size = height : size = width; Float_t rad_Ext = (Float_t)size / 2; Float_t rad_Int = (Float_t)(rad_Ext * 0.7); // Necessary pivot maps Float_t* surf_Map[2]; for (int i = 0; i < 2; i++) surf_Map[i] = new Float_t[(width + 1) * (height + 1)]; UChar_t* surf_Mask[2]; for (int i = 0; i < 2; i++) surf_Mask[i] = new UChar_t[width * height]; UChar_t* col_Map[3]; for (int i = 0; i < 3; i++) col_Map[i] = new UChar_t[width * height * 4]; // Creates the LED Off/On dome map + mask gso_Shaper::shape_Dome(surf_Map[0], surf_Mask[0], width, height, rad_Int, led_Flatness); // Sets the material for the LED gso_Material mat_Led(btn_foreColor, 0.2, 1.2, 1.8, 4); mat_Led.k_Color = btn_foreColor; // Renders the LED Off map gso_Renderer::l_Strenght(gso_Renderer::kl_Default - 0.2); gso_Shaper::shape_Render(col_Map[0], surf_Map[0], surf_Mask[0], width, height, &mat_Led, btn_backColor); // Renders the LED On map mat_Led.k_Diff = 2.0; // Self lights on! gso_Renderer::l_Strenght(gso_Renderer::kl_Default + 0.2); gso_Shaper::shape_Render(col_Map[1], surf_Map[0], surf_Mask[0], width, height, &mat_Led, btn_backColor); // Grab the desk backcolor UInt_t desk_Color = 0; gso_Shaper::map_Pixel(&desk_Color, btn_backColor); // Creates the led notch gso_Shaper::shape_Funnel(surf_Map[1], surf_Mask[1], width, height, rad_Ext, 0.7); gso_Material mat_Desk(gso_Renderer::k_Material); mat_Desk.k_Color = btn_backColor; gso_Renderer::l_Strenght(gso_Renderer::kl_Default); gso_Shaper::shape_Render(col_Map[2], surf_Map[1], surf_Mask[1], width, height, &mat_Desk, desk_Color); // Derives the notch mask as inverse of the led mask gso_Shaper::mask_Invert(surf_Mask[1], surf_Mask[0], width, height); // Generate the final maps! gso_Shaper::map_Sum(chr_Map[0], col_Map[0], surf_Mask[0], col_Map[2], surf_Mask[1], width, height, 1); //gso_Shaper::map_Copy(chr_Map[0], col_Map[2], width, height); gso_Shaper::map_Sum(chr_Map[1], col_Map[1], surf_Mask[0], col_Map[2], surf_Mask[1], width, height, 1); // Kills the pivot maps for (UInt_t i = 0; i < 2; i++) delete surf_Map[i]; for (UInt_t i = 0; i < 2; i++) delete surf_Mask[i]; for (UInt_t i = 0; i < 3; i++) delete col_Map[i]; } //______________________________________________________________________________ void gso_Button::Draw() { // Creates the object dbg_Print("gso_Button::Draw:()", DBG_LVL_MAKE); // Pivot UInt_t width = ClrWidth() + btn_Overlap * 2; UInt_t height = ClrHeight() + btn_Overlap * 2; // Sets the different status maps (Up, Down, Overed), the number of maps // varies depending of the button appearance (Button, Latch, Led, ...) UInt_t map_Count; switch (btn_Mode) { case km_Latch: map_Count = 4; break; case km_Led: map_Count = 2; break; default: map_Count = 3; } UChar_t** chr_Map = new UChar_t*[map_Count]; for (UInt_t i = 0; i < map_Count; i++) { chr_Map[i] = new UChar_t[width * height * 4]; } // Creates the appropriate maps accordingly to the button mode switch (btn_Mode) { case km_Latch: draw_Latch(chr_Map); break; case km_Led: draw_Led(chr_Map); break; default: draw_Push(chr_Map); } // Create the pixmaps used by the graphic server for (UInt_t map = 0; map < map_Count; map++) { if (frame_PxMap[map + 1]) gVirtualX->DeletePixmap(frame_PxMap[map + 1]); frame_PxMap[map + 1] = gVirtualX->CreatePixmapFromData((UChar_t*)chr_Map[map], width, height); delete []chr_Map[map]; } // Delets charmaps pointers delete []chr_Map; // Set the frame px_Map if (btn_Mode == km_Button) { (btn_Down) ? frame_PxMap[0] = frame_PxMap[2] : frame_PxMap[0] = frame_PxMap[1]; } else if (btn_Mode == km_Latch) { (btn_Down) ? frame_PxMap[0] = frame_PxMap[4] : frame_PxMap[0] = frame_PxMap[1]; } else { (btn_Down) ? frame_PxMap[0] = frame_PxMap[2] : frame_PxMap[0] = frame_PxMap[1]; } // Show the button //DoRedraw(); fClient->NeedRedraw(this); } //______________________________________________________________________________ void gso_Button::Event(Event_t* evn) { // Creates the object dbg_Print("gso_Button::Event:(Event_t*)", DBG_LVL_STEP); // Led has no events. So also skip the refresh! if (btn_Mode == km_Led) return; // Consider the left button only if (evn->fState = 256) { // Press button switch (evn->fType) { // Down case 2: if (btn_Mode == km_Button) { frame_PxMap[0] = frame_PxMap[2]; btn_Down = true; DoRedraw(); Pressed(); } else { (btn_Down) ? frame_PxMap[0] = frame_PxMap[3] : frame_PxMap[0] = frame_PxMap[2]; btn_Down = !btn_Down; DoRedraw(); Clicked(); } break; // Up (used only by in km_Button mode) case 3: if (btn_Mode == km_Button) { //(btn_Inside) ? frame_PxMap[0] = frame_PxMap[3] : frame_PxMap[0] = frame_PxMap[1]; frame_PxMap[0] = frame_PxMap[1]; btn_Down = false; DoRedraw(); Clicked(); Released(); } break; // Enter case 5: (btn_Down) ? frame_PxMap[0] = frame_PxMap[2] : frame_PxMap[0] = frame_PxMap[3]; //(btn_Down) ? frame_PxMap[0] = frame_PxMap[2] : frame_PxMap[0] = frame_PxMap[3]; DoRedraw(); btn_Inside = true; break; // Exit case 6: if (btn_Mode == km_Button) { (btn_Down) ? frame_PxMap[0] = frame_PxMap[2] : frame_PxMap[0] = frame_PxMap[1]; } else { (btn_Down) ? frame_PxMap[0] = frame_PxMap[4] : frame_PxMap[0] = frame_PxMap[1]; } DoRedraw(); btn_Inside = false; } } } //______________________________________________________________________________ UInt_t gso_Button::Mode() const { // Returns the current button mode (cannot be change one ht button // has been instantiated, at least for now) return btn_Mode; } //______________________________________________________________________________ void gso_Button::Mode(UInt_t mode) { // Resets the button mode. This will require to regenerate the maps btn_Mode = mode; // Generates new pixmaps Draw(); } //______________________________________________________________________________ UInt_t gso_Button::Status() const { // Returns the current button status if (btn_Mode == km_Latch) { if (btn_Down) return ks_Down; else return ks_Up; } else { return ks_Up; } } //______________________________________________________________________________ void gso_Button::Status(UInt_t status) { // Creates the object dbg_Print("gso_Button::Status:(UInt)", DBG_LVL_STEP); // Sets the current button status if (btn_Mode != km_Button) { // Set the appropriate status switch (status) { case ks_Up: btn_Down = false; frame_PxMap[0] = frame_PxMap[1]; break; case ks_Down: btn_Down = true; frame_PxMap[0] = frame_PxMap[2]; break; btn_Down = false; } // Refresh fClient->NeedRedraw(this); // Release the signal for the latch state if (btn_Mode == km_Latch) Clicked(); } } //______________________________________________________________________________ void gso_Button::MoveResize(Int_t left, Int_t top, UInt_t width, UInt_t height) { // TGFrame overloaded move and resize function. dbg_Print("gso_Button::MoveResize:()", DBG_LVL_STEP); // Moves and resizes the frame. Tthis will call a DoRedraw in case of need gso_Frame::MoveResize(left, top, width, height); // In case of resize button has to be redrawn Draw(); } //______________________________________________________________________________ void gso_Button::Resize(UInt_t width, UInt_t height) { // TGFrame overloaded move and resize function. dbg_Print("gso_Button::Resize:()", DBG_LVL_STEP); // Moves and resizes the frame. Tthis will call a DoRedraw in case of need gso_Frame::Resize(width, height); // In case of resize button has to be redrawn Draw(); } //______________________________________________________________________________ void gso_Button::DoRedraw() { // This function overloads the TGFrame original one. dbg_Print("gso_Button::DoRedraw:()", DBG_LVL_STEP); // Redraw the parent frame gso_Frame::DoRedraw(); // Redraws the pixmap if any available if (frame_PxMap[0]) gVirtualX->CopyArea(frame_PxMap[0], GetId(), GetGC(), 0, 0, ClrWidth() + btn_Overlap * 2, ClrHeight() + btn_Overlap * 2, ClrLeft() - btn_Overlap, ClrTop() - btn_Overlap); // Redraws the text label if any if (label_Layout) { // Label position UInt_t x = ClrLeft() + (ClrWidth() - label_Width) /2; UInt_t y = ClrTop() + (ClrHeight() - label_Height) /2; // Move label to simulate depression if (btn_Down) {x+=1; y+=1;} // Draw label_Layout->DrawText(GetId(), norm_gc_Hnd, x, y, 0, -1); } } //______________________________________________________________________________ void gso_Button::SetColor(Pixel_t color) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetColor:(UInt)", DBG_LVL_STEP); // Changes button color. btn_foreColor = color; // Redraw the button Draw(); } //______________________________________________________________________________ void gso_Button::SetColor(Pixel_t fore, Pixel_t back) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetColor:(UInt, UInt)", DBG_LVL_STEP); // Change the container frame color // Changes button color. btn_foreColor = fore; btn_backColor = back; // Redraw the button Draw(); } //______________________________________________________________________________ void gso_Button::SetBackgroundColor(Pixel_t color) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetBackgroundColor:(UInt)", DBG_LVL_STEP); // Changes button background color btn_backColor = color; // Redraw the button Draw(); } //______________________________________________________________________________ void gso_Button::SetText(const char* text) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetText:(const char*)", DBG_LVL_STEP); // Set the new button text SetText(new TGHotString(text)); } //______________________________________________________________________________ void gso_Button::SetText(const TString &label) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetText:(const TSTring)", DBG_LVL_STEP); // Set the new button text SetText(new TGHotString(label)); } //______________________________________________________________________________ void gso_Button::SetText(TGHotString *label) { // Set new button text. dbg_Print("gso_Button::SetText:(TGHotString*)", DBG_LVL_STEP); //int hotchar; //const TGMainFrame *main = (TGMainFrame *) GetMainFrame(); //std::cout << "btn_Label: " << btn_Label << "\n"; //std::cout << "Btn_Label: " << btn_Label->Data() << "\n"; //std::cout << "label: " << label << "\n"; //if (btn_Label) { //if (fHKeycode) { // main->RemoveBind(this, fHKeycode, kKeyMod1Mask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask); // main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask); //} //std::cout << "Deleting btn_Label: " << btn_Label << "\n"; //delete btn_Label; //} *btn_Label = *label; //if ((hotchar = btn_Label->GetHotChar()) != 0) { // if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) // main->BindKey(this, fHKeycode, kKeyMod1Mask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask); // main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask); //} // Redraws the label Layout(); // Asks for a redraw also } //______________________________________________________________________________ void gso_Button::SetTextColor(Pixel_t color) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetTextColor:(UInt)", DBG_LVL_STEP); // Changes text color. TGGCPool *pool = fClient->GetResourcePool()->GetGCPool(); TGGC *gc = pool->FindGC(norm_gc_Hnd); gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE); // copy gc->SetForeground(color); norm_gc_Hnd = gc->GetGC(); // Refresh //DoRedraw(); } //______________________________________________________________________________ void gso_Button::SetFont(const char* fontName, Bool_t global) { // This function overloads the TGFrame original one. dbg_Print("gso_Button::SetFont:(const char*, bool)", DBG_LVL_STEP); // Changes text font specified by name. TGFont *font = fClient->GetFont(fontName); if (font) SetFont(font->GetFontStruct(), global); } //______________________________________________________________________________ void gso_Button::SetFont(FontStruct_t font, Bool_t global) { // Changes text font. dbg_Print("gso_Button::SetFont:(FontStruct, bool)", DBG_LVL_STEP); // global is NOT implemented at this time if (font != font_Struct) { // Check if the font exist FontH_t v = gVirtualX->GetFontHandle(font); if (!v) return; // Sets the font font_Struct = font; TGGCPool *pool = fClient->GetResourcePool()->GetGCPool(); TGGC *gc = pool->FindGC(norm_gc_Hnd); gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE); // copy gc->SetFont(v); norm_gc_Hnd = gc->GetGC(); // Recalculates the button appearance Layout(); // Asks for a redraw also } } //______________________________________________________________________________ void gso_Button::Layout() { // Place the label inside the button dbg_Print("gso_Button::Layout:()", DBG_LVL_STEP); // Layouts the button label if (label_Layout) delete label_Layout; // Retrives a font TGFont *font = fClient->GetFontPool()->FindFont(font_Struct); if (!font) { font = fClient->GetFontPool()->GetFont(font_Default); font_Struct = font->GetFontStruct(); } // Calculates the size accordingly to the current label label_Layout = font->ComputeTextLayout(btn_Label->GetString(), btn_Label->GetLength(), label_WrapLength, kTextLeft, 0, &label_Width, &label_Height); // Refresh fClient->NeedRedraw(this); }