00001
00002
00003
00004
00005
00006 #ifndef OglGui_StringColumns_h
00007 #define OglGui_StringColumns_h
00008
00009 #ifndef OglGui_Window_h
00010 #include "OglGui/Window.h"
00011 #endif
00012
00013 #ifndef OglGui_DocDimensions_h
00014 #include "OglGui/DocDimensions.h"
00015 #endif
00016
00017 namespace OglGui {
00018
00019 class StringColumns : public Window,
00020 public DocDimensions
00021 {
00022 public:
00023 static const int isShadowedBit = 1;
00024 static const int isSelectedBit = 2;
00025
00026 typedef std::vector<std::string> StrVector;
00027 typedef std::vector<unsigned char> StrOptions;
00028 typedef std::vector<ULONG> StrColors;
00029
00030 struct ColumnData {
00031 ColumnData(strconst label, StrVector& strV, int w=100, ULONG bg=0)
00032 {
00033 name = label;
00034 strVector = strV;
00035 width = w;
00036 bgColor = bg;
00037 marked = 0;
00038 }
00039 std::string name;
00040 StrVector strVector;
00041 StrOptions strOptions;
00042 StrColors strColors;
00043 ULONG bgColor;
00044 int width;
00045 int marked;
00046 };
00047
00048 StringColumns(int x, int y, int w, int h) :
00049 Window(x, y, w, h)
00050 {
00051 Init(w,h);
00052 }
00053
00054 StringColumns(Window* parent, int w, int h) :
00055 Window(parent, w, h)
00056 {
00057 Init(w,h);
00058 }
00059
00060 StringColumns(Window* parent,int x,int y,int w,int h) :
00061 Window(parent, x, y, w, h)
00062 {
00063 Init(w,h);
00064 }
00065
00066 void AddColumn(strconst colName, int colWidth=100, ULONG bg=0,
00067 int insertAt=-1)
00068 {
00069 AddColumn(colName,&StrVector(),colWidth,bg,insertAt);
00070 }
00071
00072 void AddColumn(strconst colName, StrVector* strVector, int colWidth=100,
00073 ULONG bg=0, int insertAt=-1)
00074 {
00075 if (insertAt<-1) insertAt = 0;
00076 if (insertAt==-1 || insertAt>mColumns.size()-1)
00077 insertAt = mColumns.size();
00078
00079 ColumnData colData = ColumnData(colName,*strVector,colWidth,bg);
00080
00081 StrOptions strOptions = StrOptions(strVector->size(),0);
00082 colData.strOptions = strOptions;
00083
00084 StrColors strColors = StrColors(strVector->size(),oglBLACK);
00085 colData.strColors = strColors;
00086
00087 mColumns.insert(mColumns.begin()+insertAt,colData);
00088 ComputeDocHeight();
00089 }
00090
00091 void AddString(strconst str, int colIdx, ULONG col=oglBLACK,
00092 int opts=0, int insertAt=-1)
00093 {
00094 if (colIdx<0 || colIdx>mColumns.size()-1)
00095 return;
00096
00097 StrVector& strVector = mColumns[colIdx].strVector;
00098 StrOptions& strOptions = mColumns[colIdx].strOptions;
00099 StrColors& strColors = mColumns[colIdx].strColors;
00100
00101 if (insertAt<-1) insertAt = 0;
00102 if (insertAt==-1 || insertAt>strVector.size()-1)
00103 insertAt = strVector.size();
00104
00105 strVector.insert(strVector.begin()+insertAt,str);
00106 strOptions.insert(strOptions.begin()+insertAt,opts);
00107 strColors.insert(strColors.begin()+insertAt,col);
00108 ComputeDocHeight();
00109 }
00110
00111 int GetColumnIdx(strconst name)
00112 {
00113 for (int i=0; i<mColumns.size(); i++)
00114 if (mColumns[i].name == name)
00115 return i;
00116 return -1;
00117 }
00118
00119 ColumnData* GetColumnData(int colIdx)
00120 {
00121 if (colIdx<0 || colIdx>mColumns.size()-1)
00122 return 0;
00123 return &mColumns[colIdx];
00124 }
00125
00126 ColumnData* GetColumnData(strconst name)
00127 {
00128 int colIdx = GetColumnIdx(name);
00129 return GetColumnData(colIdx);
00130 }
00131
00132 void SelectRange(int col, int first, int last)
00133 {
00134 int start = (first<=last) ? first : last;
00135 int end = (first<=last) ? last : first;
00136 if (col<0 || col>mColumns.size()-1)
00137 return;
00138 StrOptions& options = mColumns[col].strOptions;
00139 if (start<0 || end<0 || start>options.size()-1 || end>options.size()-1)
00140 return;
00141 for (int i=0; i<options.size(); i++)
00142 {
00143 if (i>=start && i<=end)
00144 options[i] |= isSelectedBit;
00145 else
00146 options[i] &= ~isSelectedBit;
00147 }
00148 }
00149
00150 int FindColumn(int x)
00151 {
00152 int posX = 0;
00153 for (int i=0; i<mColumns.size(); i++)
00154 {
00155 if (x>posX && x<posX+mColumns[i].width)
00156 return i;
00157 posX += mColumns[i].width;
00158 }
00159 return -1;
00160 }
00161
00162 int FindRow(int y)
00163 {
00164 return (mDocH + mDocY - y) / mItemHeight;
00165 }
00166
00167 int FirstVisible()
00168 {
00169 return (mDocH + mDocY - H()) / mItemHeight;
00170 }
00171
00172 int LastVisible()
00173 {
00174 return (mDocH + mDocY) / mItemHeight + 1;
00175 }
00176
00177 virtual void DisplayFunc()
00178 {
00179 Window::DisplayFunc();
00180
00181 int firstVis = FirstVisible();
00182 int lastVis = LastVisible();
00183 int h0 = (mDocH + mDocY) - mItemHeight;
00184 int x = 0;
00185
00186 for (int i=0; i<mColumns.size(); i++)
00187 {
00188 StrVector& strVector = mColumns[i].strVector;
00189 int width = mColumns[i].width;
00190 ULONG bg = mColumns[i].bgColor;
00191 int bInfo[3];
00192
00193 oglSys.StartScissor(mOglWnd,x,0,width,H());
00194 oglSys.StartBlend(bInfo);
00195 SetSolidFillColor(bg);
00196 FillRectangle(x,0,width,H());
00197
00198 for (int j=firstVis; j<lastVis && j<strVector.size(); j++)
00199 DrawItem(x, h0 - j*mItemHeight, mColumns[i], j);
00200
00201 oglSys.EndBlend(bInfo);
00202 oglSys.EndScissor();
00203 x += width;
00204 }
00205 }
00206
00207 virtual void MouseFunc(int msg, int btn, int state, int x, int y)
00208 {
00209 if (msg==oglMouseDown && btn==oglLeftButton)
00210 {
00211 int c = FindColumn(x);
00212 int r = FindRow(y);
00213
00214 if (c!=-1 && r>0 && r<mColumns[c].strVector.size())
00215 {
00216 int marked = mColumns[c].marked;
00217 if (!(state & oglShift))
00218 marked = r;
00219 if (!(state & oglControl))
00220 SelectRange(c,marked,r);
00221 else
00222 ToggleOptionsBit(mColumns[c].strOptions[r],isSelectedBit);
00223 mColumns[c].marked = marked;
00224 }
00225 }
00226 Window::MouseFunc(msg,btn,state,x,y);
00227 }
00228
00229 virtual void ReshapeFunc(int w, int h)
00230 {
00231 Window::ReshapeFunc(w,h);
00232
00233
00234 mDocY += (h - mOldH);
00235 mOldH = h;
00236 if (mDocY < H() - mDocH)
00237 mDocY = H() - mDocH;
00238 if (mDocY > H() - mItemHeight)
00239 mDocY = H() - mItemHeight;
00240 }
00241
00242
00243 protected:
00244 void ToggleOptionsBit(unsigned char& options, int bit)
00245 {
00246 options = (options&bit) ? (options & ~bit) : (options | bit);
00247 }
00248
00249 void ComputeDocHeight()
00250 {
00251 int maxElem = 0;
00252 for (int i=0; i<mColumns.size(); i++)
00253 {
00254 StrVector& strVector = mColumns[i].strVector;
00255 if (strVector.size() > maxElem)
00256 maxElem = strVector.size();
00257 }
00258 mDocH = H();
00259 if (maxElem*mItemHeight > mDocH)
00260 mDocH = maxElem*mItemHeight;
00261 }
00262
00263 void DrawItem(int x, int y, ColumnData& columnData, int strIdx)
00264 {
00265 StrVector& strVector = columnData.strVector;
00266 if (strIdx<0 || strIdx>strVector.size()-1)
00267 return;
00268
00269 strconst str = columnData.strVector[strIdx];
00270 int options = columnData.strOptions[strIdx];
00271 ULONG color = columnData.strColors[strIdx];
00272 int width = columnData.width;
00273
00274 if (options & isSelectedBit)
00275 {
00276 SetSolidFillColor(oglLIGHTBLUE);
00277 FillRectangle(x,y,width,mItemHeight);
00278 }
00279 if (options & isShadowedBit)
00280 oglSys.ShadowPrintf(mOglWnd,x+4,y+4,oglLIGHTGREY,color,str.c_str());
00281 else
00282 oglSys.PosColPrintf(mOglWnd,x+4,y+4,color,str.c_str());
00283 }
00284
00285 private:
00286 void Init(int w, int h)
00287 {
00288 mDocX = mDocY = 0;
00289 mDocW = w;
00290 mDocH = h;
00291 mItemHeight = 18;
00292 mOldH = h;
00293 }
00294
00295 std::vector<ColumnData> mColumns;
00296 int mItemHeight;
00297 int mOldH;
00298 };
00299
00300 }
00301 #endif
00302