//------------------------------------------------------------------------------ // gso_Palette class -- // (C) Piero Giubilato 2008-1010, Berkeley Lab -- //------------------------------------------------------------------------------ //______________________________________________________________________________ // {Trace} // [File name] "gso_Palette.cpp" // [Author] "Piero Giubilato" // [Version] "1.5" // [Modified by] "Piero Giubilato" // [Last revision] "02 Jul 2009" // [Language] "C++" // [Compiler] "Visual C++ 9.x" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "Source for the gso_Palette class" // [Key documentation] // "Visual C++ Reference Help" // "Root reference guide" // {Trace} //______________________________________________________________________________ // Standard component #include // Root components #include // Application component #include "global.h" #include "gso_Palette.h" // CINT Preprocessor class import definition ClassImp(gso_Palette) //______________________________________________________________________________ gso_Palette::gso_Palette(const TGWindow* window, UInt_t width, UInt_t height, UInt_t bvl_Size, Float_t bvl_Thick, UInt_t foreColor, UInt_t backColor): gso_Frame(window, width, height, bvl_Size, bvl_Thick, gso_Frame::ks_Bevel, foreColor, backColor) { // Default constructor dbg_Print("gso_Palette::gso_Palette:(default)", DBG_LVL_ZERO); // Sets the xor GC xor_Font = (gClient->GetFontPool())->GetFont("Arial", -12, 40, 0); xor_gc_Set.fMask = kGCFont | kGCForeground | kGCLineWidth | kGCLineStyle | kGCFunction | kGCFillStyle | kGCFillRule; xor_gc_Set.fForeground = 0xFFFFFF; xor_gc_Set.fLineWidth = 2; xor_gc_Set.fLineStyle = kLineSolid; xor_gc_Set.fFunction = kGXxor; xor_gc_Set.fFillStyle = kFillSolid; xor_gc_Set.fFillRule = kWindingRule; xor_gc_Set.fFont = gVirtualX->GetFontHandle((FontStruct_t)xor_Font->GetFontStruct()); xor_gc_Hnd = gVirtualX->CreateGC(GetId(), &xor_gc_Set); // Enables the events handler AddInput(kButtonPressMask | kButtonReleaseMask); AddInput(kPointerMotionMask | kEnterWindowMask | kLeaveWindowMask); Connect("ProcessedEvent(Event_t*)", "gso_Palette", this, "Event(Event_t*)"); // Clears the pixmap reference frame_PxMap = 0; // Creates default palette presets and thumbs mnu_Pal = 0; UInt_t col[] = {0xFFFF00, 0x00FFFF}; color_Set(col, 2); Thumbnail(); // Mouse status mouse_start_X = 0; mouse_old_X = 0; mouse_start_Y = 0; mouse_old_Y = 0; mouse_start_B = 0; mouse_old_B = 0; mouse_curr_Mode = kmm_Out; mouse_old_Mode = kmm_Out; // Set the palette mode as map pal_Mode = km_Map; } //______________________________________________________________________________ gso_Palette::~gso_Palette() { // Default destructor dbg_Print("gso_Palette::~gso_Palette:()", DBG_LVL_ZERO); // Removes the old PixMap if any if (frame_PxMap) gVirtualX->DeletePixmap(frame_PxMap); // Removes the palette menu delete mnu_Pal; // Removes the standard palettes delete []pal_Std; for (UInt_t i = 0; i < pic_Pal.size(); i++) gClient->FreePicture(pic_Pal[i]); for (UInt_t i = 0; i < pxm_Pal.size(); i++) gVirtualX->DeletePixmap(pxm_Pal[i]); pal_std_Name.clear(); } //______________________________________________________________________________ void gso_Palette::Event(Event_t* evn) { // Handles the mouse events over the map dbg_Print("gso_Palette::Event:(Event_t*)", DBG_LVL_STEP); // Check for refresh system events if (evn->fType == 9) return; // System calls if (evn->fState > 0xFFFF) return; // This to avoid some wierd behaviours // Codify states bool key_Shift = evn->fState & 1; // Shift bool btn_Left = evn->fState >> 8 & 1; // Left mouse button down bool btn_Right = evn->fState >> 10 & 1; // Right mouse button down // Sets border area size UInt_t brd_Size = BrdSize(); UInt_t map_mid_X = BrdSize() + (ClrWidth()) / 2; UInt_t map_mid_Y = BrdSize() + (ClrHeight()) / 2; // Stores current parameters mouse_curr_X = evn->fX; mouse_curr_Y = evn->fY; // Operates only if the event started in this window // ------------------------------------------------- // Already pressed if (mouse_curr_Mode == kmm_Out) { if (evn->fState == 0) mouse_curr_Mode = kmm_None; else return; } // Exit if (evn->fType == 6 && evn->fState == 0 && mouse_curr_Mode != kmm_Square) { mouse_curr_Mode = kmm_Out; return; } // Mouse button driven actions // --------------------------- // Start references on left/right click if (mouse_curr_Mode == kmm_None && (btn_Left || btn_Right)) { // Stores reference position mouse_start_X = evn->fX; mouse_start_Y = evn->fY; mouse_start_B = evn->fState; // Set the mode as started mouse_curr_Mode = kmm_Start; } // Mode selection start if (mouse_curr_Mode == kmm_Start) { // Right click if (mouse_old_B == 1024 && evn->fState == 0) { mouse_Right(evn->fX, evn->fY); mouse_curr_Mode = kmm_None; } // Hold button if (mouse_old_B == mouse_start_B && btn_Left) mouse_curr_Mode = kmm_Drag; // Drag if (mouse_old_B == mouse_start_B && btn_Right) mouse_curr_Mode = kmm_Zoom; // Zoom if (mouse_start_B == 256 && evn->fState == 0) mouse_curr_Mode = kmm_Square; // Square // Tells the process has started mouse_Start((Float_t)evn->fY / ClrHeight()); } // Stopping current states // ----------------------- if (mouse_curr_Mode == kmm_Drag && !btn_Left) mouse_curr_Mode = kmm_None; // Stop dragging if (mouse_curr_Mode == kmm_Zoom && !btn_Right) mouse_curr_Mode = kmm_None; // Stop zooming // Stop area selection (with zoom) if (mouse_curr_Mode == kmm_Square && btn_Left) { mouse_curr_Mode = kmm_None; gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, mouse_old_X - mouse_start_X, mouse_old_Y - mouse_start_Y); // Emit stop signal mouse_Stop((Float_t)evn->fY / ClrHeight()); } // Stop area selection (no zoom) if (mouse_curr_Mode == kmm_Square && btn_Right) { mouse_curr_Mode = kmm_None; gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, mouse_old_X - mouse_start_X, mouse_old_Y - mouse_start_Y); } // Mouse motion driven actions // --------------------------- // Do square selection if (mouse_curr_Mode == kmm_Square) { // Changes Y only mouse_start_X = brd_Size + 1; evn->fX = GetWidth() - BrdSize() + 1; // Limit practical area if (evn->fX < brd_Size) evn->fX = brd_Size; if (evn->fY < BrdSize()) evn->fY = BrdSize(); if (evn->fX > GetWidth() - BrdSize() - 1) evn->fX = GetWidth() - BrdSize() - 1; if (evn->fY > GetHeight() - brd_Size - 1) evn->fY = GetHeight() - brd_Size - 1; // Clears previous selection if (mouse_old_Mode == kmm_Square) { gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, mouse_old_X - mouse_start_X, mouse_old_Y - mouse_start_Y); } // Draws new selection gVirtualX->DrawRectangle(GetId(), xor_gc_Hnd, mouse_start_X, mouse_start_Y, evn->fX - mouse_start_X, evn->fY - mouse_start_Y); } // Do fluid zooming if (mouse_curr_Mode == kmm_Zoom) { // Calculate zoom factor Float_t zY; if (evn->fY >= mouse_start_Y) { zY = 10 / (Float_t)(evn->fY - mouse_start_Y); if (zY > 1) zY = 1; } else zY = 1 + (Float_t)(mouse_start_Y - evn->fY) / 10; // Sends a signal mouse_Scale(zY); } // Do dragging if (mouse_curr_Mode == kmm_Drag) { // Calculate relative shift //Float_t relX = (Float_t)(mouse_start_X - evn->fX) / GetWidth(); Float_t relY = (Float_t)(evn->fY - mouse_start_Y) / GetHeight(); // Check border constrains //if (mouse_start_X <= brd_Size) relX = 0; if (mouse_start_Y >= GetHeight() - brd_Size) relY = 0; // Sends a signal mouse_Shift(relY); } // Stores mouse values mouse_old_X = evn->fX; mouse_old_Y = evn->fY; mouse_old_B = evn->fState; mouse_old_Mode = mouse_curr_Mode; } //______________________________________________________________________________ void gso_Palette::mouse_Right(UInt_t mX, UInt_t mY) { // Richt click event on palette dbg_Print("gso_Palette::mouse_Right:()", DBG_LVL_FLOW); // Calculates menu position Int_t posX, posY; Window_t dummyW; gVirtualX->TranslateCoordinates(GetId(), gClient->GetDefaultRoot()->GetId(), mX, mY, posX, posY, dummyW); // Shows the menu mnu_Pal->PlaceMenu(posX, posY, true, true); } //______________________________________________________________________________ void gso_Palette::mnu_pal_Do(Int_t Idx) { // Event on the palette menu dbg_Print("gso_Palette::mnu_apl_Do:()", DBG_LVL_FLOW); // Get the selected palette for (UInt_t i = 0; i < pal_Size; i++) pal_Value[i] = pal_Std[Idx * pal_Size + i]; // Refresh the palette Draw(); } //______________________________________________________________________________ void gso_Palette::Draw() { // Draws the current palette dbg_Print("gso_Palette::Draw:()", DBG_LVL_FLOW); // SpeedUp pivots UInt_t width = ClrWidth(); UInt_t height = ClrHeight(); UInt_t col_Range = color.size(); // Removes the old PixMap in case if (frame_PxMap) gVirtualX->DeletePixmap(frame_PxMap); // Creates the PixMap reference where to store the palette image. UInt_t* chr_Array = new UInt_t[width * height]; // Updates the pal array with the palette colors for (UInt_t y = 1; y <= height; y++) { for (UInt_t x = 0; x < width; x++) { switch (pal_Mode) { case km_Map: chr_Array[x + (height - y) * width] = pal_Value[(UInt_t)((Float_t)y / height * (pal_Size - 1))]; break; case km_Plot: chr_Array[x + (height - y) * width] = color[col_Range - (UInt_t)(((Float_t)y / (height + 1)) * col_Range) - 1]; break; default: break; } } } // Converts the filled char pixmap into a PxMap frame_PxMap = gVirtualX->CreatePixmapFromData((UChar_t*)chr_Array, width, height); // Delete the pivot char array delete chr_Array; // Show the palette DoRedraw(); // Emit the Updated Signal! pal_Updated(); } //______________________________________________________________________________ UInt_t gso_Palette::color_Get(UInt_t col_Id) const { // Returns the solid color color_Id dbg_Print("gso_Palette::colors_Get:(UInt)", DBG_LVL_FLOW); // Check if (col_Id >= color.size()) return 0; // Return return color[col_Id]; } //______________________________________________________________________________ void gso_Palette::color_Set(const UInt_t* col_List, UInt_t col_Count) { // Sets the palette colors. dbg_Print("gso_Palette::colors_Set:(UInt, UInt)", DBG_LVL_FLOW); // Check for the minimum number of colors if (col_Count < 1) { dbg_Print("gso_Palette::colors_Set: at least 1 color is needed to define a palette!", DBG_LVL_PLAY); return; } // Stores the pure colors for plot use color.clear(); for (UInt_t i = 0; i < col_Count; i++) color.push_back(col_List[i]); // Ad one color in case if (col_Count == 1) color.push_back(color.back()); // Generate th einternal col list UInt_t* list = new UInt_t[color.size()]; for (UInt_t i = 0; i < color.size(); i++) list[i] = color[i]; // Updates the thumbnails Thumbnail(); // Generates the palette Create(list, color.size()); // Shows the new palette Draw(); } //______________________________________________________________________________ void gso_Palette::Create(const UInt_t* col_List, UInt_t col_Count) { // Sets the palette values. 'col-List' is an array of standard RGB colors, // described in the usual way 0xRRGGBB. The function takes this color list // and generates a 256 colors palettes interpolating between the different // colors. dbg_Print("gso_Palette::Create:()", DBG_LVL_FLOW); // SpeedUp pivots UInt_t R, G, B; Float_t iPos, iRel; UInt_t iCol; for (UInt_t i = 0; i < pal_Size; i++) { // Gets where we are inside the color ramp iPos = ((Float_t)i / (pal_Size - 1))*(Float_t)(col_Count - 1); iCol = (UInt_t)floor(iPos); iRel = iPos - floor(iPos); // Interpolates color if (iRel < 1) { R = (UInt_t)((col_List[iCol] & 0xFF0000) * (1 - iRel) + (col_List[iCol + 1] & 0xFF0000) * iRel) & 0xFF0000; G = (UInt_t)((col_List[iCol] & 0x00FF00) * (1 - iRel) + (col_List[iCol + 1] & 0x00FF00) * iRel) & 0x00FF00; B = (UInt_t)((col_List[iCol] & 0x0000FF) * (1 - iRel) + (col_List[iCol + 1] & 0x0000FF) * iRel) & 0x0000FF; } else { R = (col_List[iCol] & 0xFF0000); G = (col_List[iCol] & 0x00FF00); B = (col_List[iCol] & 0x0000FF); } // Stores the palette as 4 bytes UInt_t in the ordere required by // the PxMap (BGRA). Note how the color are already correctly shifted. pal_Value[i] = B + G + R + 0; } } //______________________________________________________________________________ void gso_Palette::Thumbnail() { // Creates the palettes thumbnails dbg_Print("gso_Palette::Thumbnail:()", DBG_LVL_FLOW); // Creates the PixMap reference where to store the palette image. UInt_t pal_Count = 7; // NUmber of palettes pal_std_Name.resize(pal_Count); // Allocate the space to save the standard palettes (stacked) delete pal_Std; pal_Std = new UInt_t[pal_Count * pal_Size]; // Creates the palettes UInt_t col_List[256]; // User pal_std_Name[0].Form("0"); for (UInt_t i = 0; i < color.size(); i++) col_List[i] = color[i]; Create(col_List, color.size()); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 0 + i] = pal_Value[i]; // B&W pal_std_Name[1].Form("1"); col_List[0] = 0x0; col_List[1] = 0xFFFFFF; Create(col_List, 2); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 1 + i] = pal_Value[i]; // Spectrum pal_std_Name[2].Form("2"); col_List[0] = 0xFF0000; col_List[1] = 0xFFFF00; col_List[2] = 0x00FF00; col_List[3] = 0x00FFFF; col_List[4] = 0x0000FF; col_List[5] = 0xFF00FF; Create(col_List, 6); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 2 + i] = pal_Value[i]; // Red Yellow Green pal_std_Name[3].Form("3"); col_List[0] = 0xFF0000; col_List[1] = 0xFFFF00; col_List[2] = 0x00FF00; Create(col_List, 3); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 3 + i] = pal_Value[i]; // Black Red pal_std_Name[4].Form("4"); col_List[0] = 0x000000; col_List[1] = 0xFF0000; Create(col_List, 2); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 4 + i] = pal_Value[i]; // Black Green pal_std_Name[5].Form("5"); col_List[0] = 0x000000; col_List[1] = 0x00FF00; Create(col_List, 2); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 5 + i] = pal_Value[i]; // Balck White Black pal_std_Name[6].Form("6"); col_List[0] = 0x000000; col_List[1] = 0xFFFFFF; col_List[2] = 0x000000; Create(col_List, 3); for (UInt_t i = 0; i < pal_Size; i++) pal_Std[pal_Size * 6 + i] = pal_Value[i]; // Allocate the thumbnail space UInt_t tW = 256; UInt_t tH = 14; UInt_t tS = tW * tH; UInt_t* chr_Map = new UInt_t[pal_Count * tW * tH]; // Creates the charmaps for (UInt_t p = 0; p < pal_Count; p++) { for (UInt_t x = 0; x < tW; x++) { for (UInt_t y = 0; y < tH; y++) { chr_Map[p * tS + y * tW + x] = pal_Std[p * 256 + x]; } } } // Set pivot storage for the palette thumbs for (UInt_t i = 0; i < pic_Pal.size(); i++) gClient->FreePicture(pic_Pal[i]); for (UInt_t i = 0; i < pxm_Pal.size(); i++) gVirtualX->DeletePixmap(pxm_Pal[i]); pic_Pal.resize(pal_Count); pxm_Pal.resize(pal_Count); // Generates the picture and populate the menu delete mnu_Pal; mnu_Pal = new TGPopupMenu(); mnu_Pal->Connect(mnu_Pal, "Activated(Int_t)", "gso_Palette", this, "mnu_pal_Do(Int_t)"); for (UInt_t p = 0; p < pal_Count; p++) { pxm_Pal[p] = gVirtualX->CreatePixmapFromData((UChar_t*)&chr_Map[p * tS], tW, tH); pic_Pal[p] = gClient->GetPicturePool()->GetPicture(pal_std_Name[p].Data(), pxm_Pal[p]); if (p==1 || p== 3) mnu_Pal->AddSeparator(); // Separate the user pal mnu_Pal->AddEntry(pal_std_Name[p].Data(), p, (void*)0, pic_Pal[p]); } } //______________________________________________________________________________ void gso_Palette::palette_Mode(UInt_t mode) { // Sets the palette style. mode = km_Map set the palette to use // the provided colors to generate a 256 color palette, passing // each defined colors. mode = km_Plot uses the defined colors // as solid color, adding one box for eac of them. dbg_Print("gso_Palette::palette_Mode:(UInt)", DBG_LVL_FLOW); // Check pal_Mode = mode; Draw(); } //______________________________________________________________________________ UInt_t gso_Palette::palette_Value(UInt_t col_Id) const { // Returns the value of the Id's color of the palette. This is a safe // but slow access. For fast access use the pal_Front pointer method. dbg_Print("gso_Palette::palette_Value:(UInt)", DBG_LVL_FLOW); // Check if (col_Id < 0) col_Id = 0; if (col_Id > 255) col_Id = 255; // Return return pal_Value[col_Id]; } //______________________________________________________________________________ const UInt_t* gso_Palette::palette_Front() const { // Returns the pointer to the first element of the palette color array. // The array is 256 elements wide, be careful!! return pal_Value; } //______________________________________________________________________________ void gso_Palette::MoveResize(Int_t left, Int_t top, UInt_t width, UInt_t height) { // Overloaded move and resize function. dbg_Print("gso_Palette::MoveResize:(default)", DBG_LVL_FLOW); // Moves and resizes the palette frame. Tthis will call a DoRedraw in case of need gso_Frame::MoveResize(left, top, width, height); // Resize the palette pxMap Draw(); } //______________________________________________________________________________ void gso_Palette::Resize(UInt_t width, UInt_t height) { // Overloaded move and resize function. dbg_Print("gso_Palette::MoveResize:(default)", DBG_LVL_FLOW); // Moves and resizes the palette frame. Tthis will call a DoRedraw in case of need gso_Frame::Resize(width, height); // Resize the palette pxMap Draw(); } //______________________________________________________________________________ void gso_Palette::DoRedraw() { // Draws the current palette to the palette frame. This function // overloads the TGFrame original one. dbg_Print("gso_Palette::DoRedraw:()", DBG_LVL_FLOW); // Redraws the parent frame gso_Frame::DoRedraw(); // Redraws the palette map if any available if (frame_PxMap) gVirtualX->CopyArea(frame_PxMap, GetId(), GetGC(), 0, 0, ClrWidth(), ClrHeight(), ClrLeft(), ClrTop()); }