Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:11:53

0001 // -*- C++ -*-
0002 //
0003 // Package:     TableWidget
0004 // Class  :     FWTabularWidget
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Mon Feb  2 16:45:21 EST 2009
0011 //
0012 
0013 // system include files
0014 #include <cassert>
0015 #include <climits>
0016 #include <iostream>
0017 #include "TGResourcePool.h"
0018 
0019 // user include files
0020 #include "Fireworks/TableWidget/interface/FWTabularWidget.h"
0021 #include "Fireworks/TableWidget/interface/FWTableManagerBase.h"
0022 #include "Fireworks/TableWidget/interface/FWTableCellRendererBase.h"
0023 
0024 //
0025 // constants, enums and typedefs
0026 //
0027 
0028 //
0029 // static data member definitions
0030 //
0031 
0032 const int FWTabularWidget::kTextBuffer = 2;
0033 const int FWTabularWidget::kSeperatorWidth = 1;
0034 
0035 //
0036 // constructors and destructor
0037 //
0038 FWTabularWidget::FWTabularWidget(FWTableManagerBase* iTable, const TGWindow* p, GContext_t context)
0039     : TGFrame(p),
0040       m_table(iTable),
0041       m_widthOfTextInColumns(m_table->numberOfColumns(), static_cast<unsigned int>(0)),
0042       m_vOffset(0),
0043       m_hOffset(0),
0044       m_normGC(context),
0045       m_backgroundGC(ULONG_MAX),
0046       m_growInWidth(true) {
0047   m_textHeight = iTable->cellHeight();
0048   m_widthOfTextInColumns = m_table->maxWidthForColumns();
0049 
0050   m_tableWidth = (kTextBuffer + kTextBuffer + kSeperatorWidth) * (m_widthOfTextInColumns.size()) + kSeperatorWidth;
0051   for (std::vector<unsigned int>::const_iterator it = m_widthOfTextInColumns.begin(),
0052                                                  itEnd = m_widthOfTextInColumns.end();
0053        it != itEnd;
0054        ++it) {
0055     m_tableWidth += *it;
0056   }
0057   Resize();
0058 
0059   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier, kButtonPressMask | kButtonReleaseMask, kNone, kNone);
0060   m_table->Connect("visualPropertiesChanged()", "FWTabularWidget", this, "needToRedraw()");
0061 }
0062 
0063 // FWTabularWidget::FWTabularWidget(const FWTabularWidget& rhs)
0064 // {
0065 //    // do actual copying here;
0066 // }
0067 
0068 FWTabularWidget::~FWTabularWidget() { m_table->Disconnect("visualPropertiesChanged()", this, "needToRedraw()"); }
0069 
0070 //
0071 // assignment operators
0072 //
0073 // const FWTabularWidget& FWTabularWidget::operator=(const FWTabularWidget& rhs)
0074 // {
0075 //   //An exception safe implementation is
0076 //   FWTabularWidget temp(rhs);
0077 //   swap(rhs);
0078 //
0079 //   return *this;
0080 // }
0081 
0082 //
0083 // member functions
0084 //
0085 void FWTabularWidget::dataChanged() {
0086   m_textHeight = m_table->cellHeight();
0087   setWidthOfTextInColumns(m_table->maxWidthForColumns());
0088 }
0089 
0090 void FWTabularWidget::needToRedraw() { fClient->NeedRedraw(this); }
0091 
0092 void FWTabularWidget::setWidthOfTextInColumns(const std::vector<unsigned int>& iNew) {
0093   assert(iNew.size() == static_cast<unsigned int>(m_table->numberOfColumns()));
0094 
0095   m_widthOfTextInColumns = iNew;
0096   if (m_growInWidth) {
0097     // with of columns grow to prevent resizing/flickering on next event
0098     m_widthOfTextInColumnsMax.resize(iNew.size());
0099     std::vector<unsigned int>::iterator k = m_widthOfTextInColumnsMax.begin();
0100     for (std::vector<unsigned int>::iterator it = m_widthOfTextInColumns.begin(); it != m_widthOfTextInColumns.end();
0101          ++it, ++k) {
0102       if (*it < *k)
0103         *it = *k;
0104       else
0105         *k = *it;
0106     }
0107   }
0108 
0109   m_tableWidth = 0;
0110   for (std::vector<unsigned int>::const_iterator it = m_widthOfTextInColumns.begin(),
0111                                                  itEnd = m_widthOfTextInColumns.end();
0112        it != itEnd;
0113        ++it) {
0114     m_tableWidth += *it + kTextBuffer + kTextBuffer + kSeperatorWidth;
0115   }
0116   m_tableWidth += kSeperatorWidth;
0117 }
0118 
0119 void FWTabularWidget::setVerticalOffset(UInt_t iV) {
0120   if (iV != m_vOffset) {
0121     m_vOffset = iV;
0122     fClient->NeedRedraw(this);
0123   }
0124 }
0125 void FWTabularWidget::setHorizontalOffset(UInt_t iH) {
0126   if (iH != m_hOffset) {
0127     m_hOffset = iH;
0128     fClient->NeedRedraw(this);
0129   }
0130 }
0131 
0132 Bool_t FWTabularWidget::HandleButton(Event_t* event) {
0133   if (event->fType == kButtonPress) {
0134     Int_t row, col, relX, relY;
0135     translateToRowColumn(event->fX, event->fY, row, col, relX, relY);
0136     //std::cout <<"Press: "<<relX<<" "<<relY<<" "<<row<<" "<<col<<" "<<m_table->numberOfRows()<<" "<<m_table->numberOfColumns()<<std::endl;
0137     if (row >= 0 && row < m_table->numberOfRows() && col >= 0 && col < m_table->numberOfColumns()) {
0138       FWTableCellRendererBase* renderer = m_table->cellRenderer(row, col);
0139       if (renderer) {
0140         renderer->buttonEvent(event, relX, relY);
0141       }
0142       buttonPressed(row, col, event, relX, relY);
0143     }
0144     return true;
0145   }
0146   if (event->fType == kButtonRelease) {
0147     Int_t row, col, relX, relY;
0148     translateToRowColumn(event->fX, event->fY, row, col, relX, relY);
0149     //std::cout <<"Release: "<<relX<<" "<<relY<<" "<<row<<" "<<col<<" "<<m_table->numberOfRows()<<" "<<m_table->numberOfColumns()<<std::endl;
0150     if (row >= 0 && row < m_table->numberOfRows() && col >= 0 && col < m_table->numberOfColumns()) {
0151       FWTableCellRendererBase* renderer = m_table->cellRenderer(row, col);
0152       if (renderer) {
0153         renderer->buttonEvent(event, relX, relY);
0154       }
0155       buttonReleased(row, col, event, relX, relY);
0156     }
0157     return true;
0158   }
0159   return false;
0160 }
0161 
0162 void FWTabularWidget::translateToRowColumn(
0163     Int_t iX, Int_t iY, Int_t& oRow, Int_t& oCol, Int_t& oRelX, Int_t& oRelY) const {
0164   if (iX < 0) {
0165     oCol = -1;
0166     oRelX = 0;
0167   } else {
0168     if (iX + static_cast<Int_t>(m_hOffset) > static_cast<Int_t>(m_tableWidth)) {
0169       oCol = m_widthOfTextInColumns.size();
0170       oRelX = 0;
0171     } else {
0172       iX += m_hOffset;
0173       oCol = 0;
0174       for (std::vector<unsigned int>::const_iterator it = m_widthOfTextInColumns.begin(),
0175                                                      itEnd = m_widthOfTextInColumns.end();
0176            it != itEnd;
0177            ++it, ++oCol) {
0178         oRelX = iX - kTextBuffer;
0179         iX -= 2 * kTextBuffer + kSeperatorWidth + *it;
0180         if (iX <= 0) {
0181           break;
0182         }
0183       }
0184     }
0185   }
0186   if (iY < 0) {
0187     oRow = -1;
0188     oRelY = 0;
0189   } else {
0190     oRow = (int)(float(iY + m_vOffset) / (m_textHeight + 2 * kTextBuffer + kSeperatorWidth));
0191     oRelY = iY - oRow * (m_textHeight + 2 * kTextBuffer + kSeperatorWidth) + m_vOffset - kTextBuffer;
0192     Int_t numRows = m_table->numberOfRows();
0193     if (oRow > numRows) {
0194       oRow = numRows;
0195       oRelY = 0;
0196     }
0197   }
0198 }
0199 
0200 void FWTabularWidget::buttonPressed(Int_t row, Int_t column, Event_t* event, Int_t relX, Int_t relY) {
0201   //std::cout <<"buttonPressed "<<row<<" "<<column<<std::endl;
0202   Long_t args[5];
0203   args[0] = (Long_t)row;
0204   args[1] = (Long_t)column;
0205   args[2] = (Long_t)event;
0206   args[3] = (Long_t)relX;
0207   args[4] = (Long_t)relY;
0208   Emit("buttonPressed(Int_t,Int_t,Event_t*,Int_t,Int_t)", args);
0209 }
0210 void FWTabularWidget::buttonReleased(Int_t row, Int_t column, Event_t* event, Int_t relX, Int_t relY) {
0211   //std::cout <<"buttonReleased "<<row<<" "<<column<<std::endl;
0212   Long_t args[6];
0213   args[0] = (Long_t)row;
0214   args[1] = (Long_t)column;
0215   args[2] = (Long_t)event;
0216   args[3] = (Long_t)relX;
0217   args[4] = (Long_t)relY;
0218   Emit("buttonReleased(Int_t,Int_t,Event_t*,Int_t,Int_t)", args);
0219 }
0220 
0221 void FWTabularWidget::DoRedraw() {
0222   TGFrame::DoRedraw();
0223 
0224   //std::cout <<"DoRedraw "<<m_tableWidth<<std::endl;
0225 
0226   const int yOrigin = -m_vOffset;
0227   const int xOrigin = -m_hOffset;
0228   const int visibleWidth = m_tableWidth + xOrigin - kSeperatorWidth;
0229   int y = yOrigin;
0230   if (m_backgroundGC != ULONG_MAX) {
0231     gVirtualX->FillRectangle(fId, m_backgroundGC, xOrigin, y, m_tableWidth, GetHeight());
0232   }
0233   gVirtualX->DrawLine(fId, m_normGC, xOrigin, y, visibleWidth, y);
0234   //Draw data
0235   const int numRows = m_table->numberOfRows();
0236 
0237   //figure out which rows and columns are visible
0238   Int_t startRow, startColumn, relX, relY;
0239   translateToRowColumn(0, 0, startRow, startColumn, relX, relY);
0240   if (startRow < 0) {
0241     startRow = 0;
0242   }
0243   if (startColumn < 0) {
0244     startColumn = 0;
0245   }
0246   Int_t endRow, endColumn;
0247   translateToRowColumn(GetWidth(), GetHeight(), endRow, endColumn, relX, relY);
0248   if (endRow >= numRows) {
0249     endRow = numRows - 1;
0250   }
0251   if (endColumn >= static_cast<Int_t>(m_widthOfTextInColumns.size())) {
0252     endColumn = m_widthOfTextInColumns.size() - 1;
0253   }
0254   //std::cout <<"start "<<startRow<<" "<<startColumn<<" end "<<endRow<<" "<<endColumn<<std::endl;
0255 
0256   //calculate offset for rows and columns
0257   Int_t rowOffset = (kSeperatorWidth + 2 * kTextBuffer + m_textHeight) * startRow;
0258   Int_t columnOffset = kSeperatorWidth + kTextBuffer + xOrigin;
0259   for (std::vector<unsigned int>::iterator itTextWidth = m_widthOfTextInColumns.begin(),
0260                                            itEnd = m_widthOfTextInColumns.begin() + startColumn;
0261        itTextWidth != itEnd;
0262        ++itTextWidth) {
0263     columnOffset += *itTextWidth + kTextBuffer + kSeperatorWidth + kTextBuffer;
0264   }
0265 
0266   y += rowOffset;
0267   for (int row = startRow; row <= endRow; ++row) {
0268     std::vector<unsigned int>::iterator itTextWidth = m_widthOfTextInColumns.begin() + startColumn;
0269     //int x=kSeperatorWidth+kTextBuffer+xOrigin;
0270     int x = columnOffset;
0271     y += kTextBuffer + kSeperatorWidth;
0272     for (int col = startColumn; col <= endColumn; ++col, ++itTextWidth) {
0273       m_table->cellRenderer(row, col)->draw(fId, x, y, *itTextWidth, m_textHeight);
0274       //UInt_t textWidth = font->TextWidth(itData->c_str(),-1);
0275       x += *itTextWidth + kTextBuffer + kSeperatorWidth + kTextBuffer;
0276     }
0277     y += +m_textHeight + kTextBuffer;
0278     gVirtualX->DrawLine(fId, m_normGC, xOrigin, y, visibleWidth, y);
0279   }
0280 
0281   //draw column separators
0282   int x = xOrigin;
0283   gVirtualX->DrawLine(fId, m_normGC, x, 0, x, y);
0284   x += kSeperatorWidth;
0285   for (std::vector<unsigned int>::iterator itTextWidth = m_widthOfTextInColumns.begin();
0286        itTextWidth != m_widthOfTextInColumns.end();
0287        ++itTextWidth) {
0288     x += 2 * kTextBuffer + *itTextWidth;
0289     gVirtualX->DrawLine(fId, m_normGC, x, 0, x, y);
0290     x += kSeperatorWidth;
0291   }
0292 }
0293 
0294 void FWTabularWidget::setLineContext(GContext_t iContext) { m_normGC = iContext; }
0295 void FWTabularWidget::setBackgroundAreaContext(GContext_t iContext) { m_backgroundGC = iContext; }
0296 
0297 //
0298 // const member functions
0299 //
0300 TGDimension FWTabularWidget::GetDefaultSize() const {
0301   // returns default size
0302 
0303   UInt_t w = fWidth;
0304   if (!(GetOptions() & kFixedWidth)) {
0305     w = m_tableWidth;
0306   }
0307   UInt_t h = fHeight;
0308   if (!(GetOptions() & kFixedHeight)) {
0309     unsigned int numRows = m_table->numberOfRows();
0310 
0311     h = kSeperatorWidth + (m_textHeight + 2 * kTextBuffer + kSeperatorWidth) * (numRows);
0312   }
0313   return TGDimension(w, h);
0314 }
0315 
0316 //
0317 // static member functions
0318 //
0319 const TGGC& FWTabularWidget::getDefaultGC() {
0320   static const TGGC* s_default = gClient->GetResourcePool()->GetFrameGC();
0321   return *s_default;
0322 }
0323 
0324 ClassImp(FWTabularWidget);