00001
00002
00003 #ifndef Impala_Application_TagsLife_TagsWeekPlot_h
00004 #define Impala_Application_TagsLife_TagsWeekPlot_h
00005
00006 #ifndef OglGui_WindowView2D_h
00007 #include "OglGui/WindowView2D.h"
00008 #endif
00009
00010 #include "Tag.h"
00011
00012 namespace Impala {
00013 namespace Application {
00014 namespace TagsLife {
00015
00016 class TagsWeekPlot : public OglGui::Window,
00017 public OglGui::WindowListener
00018 {
00019 public:
00020 typedef OglGui::Window Window;
00021 typedef OglGui::WindowView2D WindowView2D;
00022 typedef OglGui::StaticText StaticText;
00023
00024 TagsWeekPlot(Window* parent, int x, int y, int w, int h, int nrView=100) :
00025 Window(parent,x,y,w,h)
00026 {
00027 Init(w,h,nrView);
00028 }
00029
00030 void SetImage(int idx, OGLIMAGE* im)
00031 {
00032 if (idx < 0 || idx >= mOglImages.size())
00033 return;
00034 ReleaseOglImage(mOglImages[idx]);
00035 if (im)
00036 im->refCount++;
00037 mOglImages[idx] = im;
00038 }
00039
00040 void ShowRange(int first, int last)
00041 {
00042 mFirstVisible = first;
00043 mLastVisible = last;
00044 }
00045
00046 void BarColors(ULONG borderCol, ULONG bgCol, ULONG fillCol)
00047 {
00048 mBarBorderColor = borderCol;
00049 mBarBgColor = bgCol;
00050 mBarFillColor = fillCol;
00051 }
00052
00053 int FirstVisible() { return mFirstVisible; }
00054 int LastVisible() { return mLastVisible; }
00055 void MinimumViewSize(int sz) { mMinViewSize = sz; }
00056 int MinimumViewSize() { return mMinViewSize; }
00057
00058
00059 void Clear()
00060 {
00061 mMaxFreq = 0;
00062 mHistogram.clear();
00063 mFills.clear();
00064
00065 for (int i=0; i<mOglImages.size(); i++)
00066 ReleaseOglImage(mOglImages[i]);
00067 mOglImages.clear();
00068 }
00069
00070 void AddToHistogram(int val, float fillPerc = 0.f, OGLIMAGE* oglIm=0)
00071 {
00072 if (val > mMaxFreq) {
00073 mMaxFreq = val;
00074 double newMin, newMax;
00075 double step = findStep(0.0, (double) mMaxFreq, newMin, newMax);
00076 mStep = ceil(step);
00077 mMaxFreq = ceil(newMax);
00078 }
00079
00080 mHistogram.push_back(val);
00081 mFills.push_back(fillPerc);
00082 mOglImages.push_back(oglIm);
00083 if (oglIm !=0 )
00084 oglIm->refCount++;
00085 }
00086
00087 int NrVisible()
00088 {
00089 return mLastVisible-mFirstVisible+1;
00090 }
00091
00092 virtual void DisplayFunc()
00093 {
00094 OGC oldOGC;
00095 OGCSave(&oldOGC);
00096 Window::DisplayFunc();
00097 if (NrVisible() != 0)
00098 {
00099 ShowHistogram();
00100 HandleViews();
00101 HandleDetailView();
00102 }
00103 OGCRestore(&oldOGC);
00104 }
00105
00106
00107 virtual void
00108 WindowMouseEvent(OglGui::Window *src, int msg, int but, int state,
00109 int x, int y, void *userData )
00110 {
00111 if (userData == (void*) WNDVIEW2D_IDX)
00112 WndView2DMouseEvent((WindowView2D*)src,msg);
00113 if (userData == (void*) WEEKWND_IDX)
00114 WeekWndMouseEvent(src,msg,x,y);
00115 }
00116
00117 protected:
00118
00119
00120 void WndView2DMouseEvent(WindowView2D* wndView2D, int msg)
00121 {
00122 if (msg == oglMouseEnter )
00123 {
00124 mDetailRef = wndView2D;
00125 mDetailView->SetImage(wndView2D->GetOglView()->im);
00126 int topX = wndView2D->W()/2-50;
00127 int topY = -120;
00128 ToTopWindow(wndView2D,topX,topY);
00129 mDetailView->SetDimensions(topX,topY,100,100);
00130 mDetailView->SetVisible(true);
00131 }
00132 if (msg == oglMouseLeave)
00133 mDetailView->SetVisible(false);
00134 }
00135
00136
00137 void WeekWndMouseEvent(Window* wnd, int msg, int x, int y)
00138 {
00139 int nrVis = NrVisible();
00140
00141 if (nrVis!=0 && (msg == oglMouseEnter || msg == oglMouseMove))
00142 {
00143 int topX = AXIS_X + x + 10;
00144 int topY = -30;
00145
00146 ToTopWindow(this,topX,topY);
00147 mWeekText->SetDimensions(topX,topY,180,20);
00148 mWeekText->SetVisible(true);
00149
00150 float slotSz = (W() - AXIS_X) / (float) nrVis;
00151 int weekNr = mFirstVisible + x / slotSz;
00152
00153 mWeekText->SetText(Tag::flickrWeekToString(weekNr));
00154 }
00155 if (msg == oglMouseLeave)
00156 mWeekText->SetVisible(false);
00157 }
00158
00159 void HandleViews()
00160 {
00161 int nrVis = NrVisible();
00162 float slotSz = (W() - AXIS_X) / (float) nrVis;
00163
00164 for (int i=0; i<mNrViews; i++)
00165 {
00166 mWndViews[i]->SetVisible(i<nrVis && slotSz>=mMinViewSize);
00167 if (slotSz < mMinViewSize)
00168 continue;
00169 int x = AXIS_X + i * slotSz;
00170 mWndViews[i]->SetDimensions(x,AXIS_Y,slotSz,slotSz);
00171 mWndViews[i]->SetImage(i>=nrVis ? 0 : mOglImages[mFirstVisible+i]);
00172 }
00173 }
00174
00175 void ShowWeekNr(int weekNr, int x, int slotSz)
00176 {
00177 if (slotSz < 24)
00178 return;
00179
00180 int txtX, txtY;
00181 char buf[10];
00182 sprintf(buf,"%d", weekNr);
00183 oglSys.AlignTextXY(mOglWnd,buf,oglCenterAlign,oglCenterAlign,
00184 slotSz, 20, &txtX, &txtY);
00185 oglSys.PosColPrintf(mOglWnd,x+txtX,txtY+2,mBarBorderColor,buf);
00186 }
00187
00188 void ShowLabel(int value, int y)
00189 {
00190 int txtX, txtY;
00191 char buf[10];
00192 sprintf(buf,"%d", value);
00193 oglSys.AlignTextXY(mOglWnd,buf,oglRightAlign,oglBottomAlign,
00194 AXIS_X-3, 0, &txtX, &txtY);
00195 oglSys.PosColPrintf(mOglWnd,txtX,y-4,mBarBorderColor,buf);
00196 }
00197
00198 void ShowHistogram()
00199 {
00200 float slotSz = (W() - AXIS_X) / (float) NrVisible();
00201 float binSz = (slotSz >= 2) ? slotSz / 2 : 1;
00202 float viewH = (slotSz >= mMinViewSize) ? slotSz : 0;
00203 bool oneCol = mBarBgColor == mBarFillColor &&
00204 mBarBgColor == mBarBorderColor;
00205
00206 int yHeight = H()-AXIS_Y-viewH-7;
00207
00208 for (int i=mFirstVisible; i<=mLastVisible; i++)
00209 {
00210 int x = AXIS_X + (i-mFirstVisible) * slotSz;
00211 int barH = (mHistogram[i]/(float) mMaxFreq) * yHeight;
00212
00213 if (barH >= 1)
00214 {
00215 SetSolidFillColor(mBarBgColor);
00216 FillRectangle(x+slotSz/4,AXIS_Y+viewH,binSz,barH);
00217 }
00218 if (!oneCol && mFills[i] * barH >= 1)
00219 {
00220 SetSolidFillColor(mBarFillColor);
00221 FillRectangle(x+slotSz/4,AXIS_Y+viewH,binSz,mFills[i]*barH);
00222 }
00223 if (!oneCol && barH >= 1)
00224 {
00225 SetSolidLineColor(mBarBorderColor);
00226 DrawRectangle(x+slotSz/4,AXIS_Y+viewH,binSz,barH);
00227 }
00228 ShowWeekNr(i, x, slotSz);
00229 }
00230
00231 SetSolidLineColor(mBarBorderColor);
00232 DrawRectangle(AXIS_X+1, AXIS_Y+viewH, 0, yHeight);
00233 for(long i=0; i <= mMaxFreq; i+= mStep) {
00234
00235 int y = (i/(float) mMaxFreq) * yHeight+AXIS_Y+viewH;
00236 DrawRectangle(AXIS_X, y, -3, 0);
00237 ShowLabel(i, y);
00238 }
00239 }
00240
00241
00242 void HandleDetailView()
00243 {
00244 if (!mDetailView->GetVisible())
00245 return;
00246
00247 int x,y,w,h;
00248 mDetailRef->GetDimensions(x,y,w,h);
00249 SetSolidLineColor(oglRED);
00250 DrawLine(x,y,x+w/2-50,y-AXIS_Y);
00251 DrawLine(x+w,y,x+w/2+50,y-AXIS_Y);
00252 }
00253
00254 private:
00255 void Init(int w, int h, int nrView)
00256 {
00257 mFirstVisible = 0;
00258 mLastVisible = 10;
00259 mNrViews = nrView;
00260 mMinViewSize = 8;
00261 mMaxFreq = 0;
00262
00263 mBarBorderColor = oglRED;
00264 mBarBgColor = oglRED;
00265 mBarFillColor = oglRED;
00266
00267 for (int i=0; i<mNrViews; i++)
00268 {
00269 WindowView2D* wndView = new WindowView2D(this,0,0,10,10,0);
00270 wndView->Texturing(false);
00271 wndView->SetVisible(false);
00272
00273 wndView->SetWindowListener(this,WNDVIEW2D_IDX);
00274 mWndViews.push_back(wndView);
00275 }
00276
00277 Window* topWnd = this;
00278 while(topWnd->GetParent())
00279 topWnd = topWnd->GetParent();
00280 mDetailView = new WindowView2D(topWnd,0,0,10,10,0);
00281 mDetailView->Texturing(false);
00282
00283 mDetailView->SetVisible(false);
00284
00285 mWeekSensorWnd = new Window(this,AXIS_X,0,w,AXIS_Y);
00286 mWeekSensorWnd->ConnectTo(this,OglGui::TOLEFTRIGHT);
00287 mWeekSensorWnd->SetWindowListener(this,WEEKWND_IDX);
00288
00289 mWeekSensorWnd->GetOGLWND()->allMouseMotion = 1;
00290
00291 mWeekText = new StaticText(topWnd,0,0,100,20,"");
00292 mWeekText->SetRoundness(20,20,20,20);
00293 mWeekText->SetBorderType(BEV_LINE);
00294 mWeekText->SetBorderFillShaded(2);
00295 mWeekText->SetVisible(false);
00296 }
00297
00298 double findStep(double min, double max, double& newMin, double& newMax) {
00299 double range = max - min;
00300 if(range < 0) range *= -1;
00301 double exponent = floor(log10(range));
00302 double coefficient = range/pow(10, exponent);
00303
00304 double step = 1;
00305 if(coefficient <= 5) {
00306 step = 0.5;
00307 if(coefficient <= 2.5) {
00308 step = 0.25;
00309 if(coefficient == 1) step = 0.1;
00310 }
00311 }
00312
00313 step *= pow(10, exponent);
00314 if(step == 2.5) step = 2;
00315
00316 newMin = floor(min/step)*step;
00317 newMax = ceil(max/step)*step;
00318
00319 if(min > max) return -step;
00320 return step;
00321 }
00322 double findStep(double& min, double& max) {return findStep(min, max, min, max);}
00323
00324
00325 std::vector<int> mHistogram;
00326 std::vector<float> mFills;
00327 std::vector<OGLIMAGE*> mOglImages;
00328 std::vector<WindowView2D*> mWndViews;
00329
00330 WindowView2D* mDetailView;
00331 WindowView2D* mDetailRef;
00332
00333 Window* mWeekSensorWnd;
00334 StaticText* mWeekText;
00335
00336 int mNrViews;
00337 int mFirstVisible;
00338 int mLastVisible;
00339 int mMinViewSize;
00340 long mMaxFreq;
00341 int mStep;
00342
00343 ULONG mBarBorderColor;
00344 ULONG mBarBgColor;
00345 ULONG mBarFillColor;
00346
00347 const static int AXIS_X = 65;
00348 const static int AXIS_Y = 20;
00349 const static int WNDVIEW2D_IDX = 1;
00350 const static int WEEKWND_IDX = 2;
00351 };
00352
00353 }
00354 }
00355 }
00356
00357 #endif