961 lines
24 KiB
C++
961 lines
24 KiB
C++
// Calendar Control version 2.5
|
|
// by Al.V. Sarikov.
|
|
// Kherson, Ukraine, 2006.
|
|
// E-mail: avix@ukrpost.net.
|
|
// Home page: http://avix.pp.ru.
|
|
|
|
// Control which allows to work with dates:
|
|
// enter date to text field and choose it from calendar.
|
|
|
|
// Distributed under BSD license (see LICENSE file).
|
|
|
|
#include <Bitmap.h>
|
|
#include <View.h>
|
|
#include <time.h>
|
|
#include <ControlLook.h>
|
|
#include "MouseSenseStringView.cpp"
|
|
|
|
|
|
class MonthView : public BView
|
|
{
|
|
public:
|
|
MonthView(int day, int month, int year, int first_year, int last_year);
|
|
~MonthView();
|
|
virtual void AttachedToWindow(void);
|
|
virtual void Draw(BRect r);
|
|
virtual void KeyDown(const char *bytes, int32 numBytes);
|
|
virtual void MessageReceived(BMessage *msg);
|
|
virtual void MouseDown(BPoint p);
|
|
virtual void MouseUp(BPoint p);
|
|
void MouseMoved(BPoint pt, uint32 transit, const BMessage *msg);
|
|
|
|
private:
|
|
void DrawMonth();
|
|
|
|
BMessenger *msng;
|
|
MouseSenseStringView *yearMStringView[2];
|
|
MouseSenseStringView *monthMStringView[2];
|
|
|
|
MouseSenseStringView *todayStringView;
|
|
BStringView *monthStringView;
|
|
BStringView *yearStringView;
|
|
char *weekdayNames[7];
|
|
char *monthNames[12];
|
|
int monthDays[12];
|
|
|
|
BBitmap *Bmp;
|
|
BView *BmpView;
|
|
|
|
int cday, cmonth, cyear; // current date in window
|
|
int cwday1; // day of week of 1st of month in window
|
|
int cwday; // day of week of current day of month in window
|
|
|
|
int first_year, last_year;
|
|
|
|
int tday, tmonth, tyear; // today
|
|
int twday; // is needed to calculate days of week
|
|
|
|
float h_cell, w_cell; // height and width of cell for one number of day of nonth
|
|
|
|
BRect cursor; // rectangle arounding chosen date
|
|
|
|
BRect cursorPressed; // rectangle arounding date where mouse was pressed
|
|
bool MousePressed; // is mouse pressed on date
|
|
int dayPressed; // date where mouse is pressed
|
|
|
|
bool NewMonth; // if true field must be cleared
|
|
|
|
int which_focused; // 0 - if month, 1 - if year,
|
|
// 2 - if days of month, 3 - if today
|
|
};
|
|
|
|
|
|
MonthView::MonthView(int day, int month, int year, int first_year, int last_year)
|
|
:BView(BRect(0,0,100,100), "MonthViewAViX", B_FOLLOW_LEFT, B_WILL_DRAW)
|
|
{
|
|
this->cday=day;
|
|
this->cmonth=month;
|
|
this->cyear=year;
|
|
|
|
this->first_year=first_year;
|
|
this->last_year=last_year;
|
|
|
|
struct tm *dat;
|
|
time_t tmp;
|
|
time(&tmp);
|
|
dat=localtime(&tmp);
|
|
|
|
tday=dat->tm_mday;
|
|
tmonth=dat->tm_mon+1;
|
|
tyear=dat->tm_year+1900; // new day coming when window is opened is not handled
|
|
// because it is very rear case
|
|
twday=dat->tm_wday;
|
|
|
|
weekdayNames[0]=(char*)"Mo";
|
|
weekdayNames[1]=(char*)"Tu";
|
|
weekdayNames[2]=(char*)"We";
|
|
weekdayNames[3]=(char*)"Th";
|
|
weekdayNames[4]=(char*)"Fr";
|
|
weekdayNames[5]=(char*)"Sa";
|
|
weekdayNames[6]=(char*)"Su";
|
|
|
|
monthNames[0]=(char*)"January";
|
|
monthNames[1]=(char*)"February";
|
|
monthNames[2]=(char*)"March";
|
|
monthNames[3]=(char*)"April";
|
|
monthNames[4]=(char*)"May";
|
|
monthNames[5]=(char*)"June";
|
|
monthNames[6]=(char*)"July";
|
|
monthNames[7]=(char*)"August";
|
|
monthNames[8]=(char*)"September";
|
|
monthNames[9]=(char*)"October";
|
|
monthNames[10]=(char*)"November";
|
|
monthNames[11]=(char*)"December";
|
|
|
|
monthDays[0]=31;
|
|
monthDays[1]=28;
|
|
monthDays[2]=31;
|
|
monthDays[3]=30;
|
|
monthDays[4]=31;
|
|
monthDays[5]=30;
|
|
monthDays[6]=31;
|
|
monthDays[7]=31;
|
|
monthDays[8]=30;
|
|
monthDays[9]=31;
|
|
monthDays[10]=30;
|
|
monthDays[11]=31;
|
|
|
|
NewMonth=false; // first field is cleared and clearing is not needed
|
|
|
|
MousePressed=false;
|
|
}
|
|
|
|
|
|
MonthView::~MonthView()
|
|
{
|
|
delete todayStringView;
|
|
delete monthStringView;
|
|
delete monthMStringView[0];
|
|
delete monthMStringView[1];
|
|
delete yearStringView;
|
|
delete yearMStringView[0];
|
|
delete yearMStringView[1];
|
|
delete msng;
|
|
Bmp->RemoveChild(BmpView);
|
|
delete BmpView;
|
|
delete Bmp;
|
|
}
|
|
|
|
|
|
void MonthView::AttachedToWindow(void)
|
|
{
|
|
SetFont(be_plain_font);
|
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
|
|
// Calculate size of cell needed for number of day of month
|
|
font_height h;
|
|
be_plain_font->GetHeight(&h);
|
|
h_cell = (int)(h.ascent+h.descent+h.leading+6);
|
|
w_cell = StringWidth("4")*4;
|
|
|
|
// add today's date
|
|
BString s("");
|
|
s << tday << " " << monthNames[tmonth-1] << " " << tyear;
|
|
|
|
msng=new BMessenger(this);
|
|
todayStringView=new MouseSenseStringView(new BMessage('TODA'), msng,
|
|
BRect(10,10,100,100),"todayMStringViewAViX", s.String());
|
|
todayStringView->ResizeToPreferred();
|
|
todayStringView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
AddChild(todayStringView);
|
|
|
|
// add month selection
|
|
monthStringView=new BStringView(BRect(10,10,100,100),"monthStringViewAViX", monthNames[8]);
|
|
monthStringView->SetAlignment(B_ALIGN_CENTER);
|
|
monthStringView->ResizeToPreferred();
|
|
monthStringView->SetText(monthNames[cmonth-1]);
|
|
monthStringView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
AddChild(monthStringView);
|
|
|
|
// add year selection
|
|
s.SetTo("");
|
|
if(cyear<10) s.Append("000");
|
|
else if(cyear<100) s.Append("00");
|
|
else if(cyear<1000) s.Append("0");
|
|
s << cyear;
|
|
yearStringView=new BStringView(BRect(10,10,100,100),"yearStringViewAViX",
|
|
"0000");
|
|
yearStringView->ResizeToPreferred();
|
|
yearStringView->SetText(s.String());
|
|
yearStringView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
AddChild(yearStringView);
|
|
|
|
ResizeTo(w_cell*7+1,h_cell*7+3+16+yearStringView->Bounds().bottom+todayStringView->Bounds().bottom);
|
|
Window()->ResizeTo(Bounds().right, Bounds().bottom);
|
|
|
|
// year to the left button
|
|
yearMStringView[0]=new MouseSenseStringView(new BMessage('YEA0'),msng,
|
|
BRect(10,10,100,100),
|
|
"yearMStringViewAViX0",
|
|
"<<");
|
|
AddChild(yearMStringView[0]);
|
|
yearMStringView[0]->ResizeToPreferred();
|
|
yearMStringView[0]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
|
|
// year to the right button
|
|
yearMStringView[1]=new MouseSenseStringView(new BMessage('YEA1'),msng,
|
|
BRect(10,10,100,100),
|
|
"yearMStringViewAViX1",
|
|
">>");
|
|
AddChild(yearMStringView[1]);
|
|
yearMStringView[1]->ResizeToPreferred();
|
|
yearMStringView[1]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
|
|
// month to the left button
|
|
monthMStringView[0]=new MouseSenseStringView(new BMessage('MON0'),msng,
|
|
BRect(10,10,100,100),
|
|
"monthMStringViewAViX0",
|
|
"<<");
|
|
AddChild(monthMStringView[0]);
|
|
monthMStringView[0]->ResizeToPreferred();
|
|
monthMStringView[0]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
|
|
// month to the right button
|
|
monthMStringView[1]=new MouseSenseStringView(new BMessage('MON1'),msng,
|
|
BRect(10,10,100,100),
|
|
"monthMStringViewAViX1",
|
|
">>");
|
|
AddChild(monthMStringView[1]);
|
|
monthMStringView[1]->ResizeToPreferred();
|
|
monthMStringView[1]->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
|
|
// move all in correct position
|
|
todayStringView->MoveTo((Bounds().right-todayStringView->Bounds().right)/2,
|
|
Bounds().bottom-todayStringView->Bounds().bottom-2);
|
|
|
|
if(tyear<first_year || tyear>last_year) todayStringView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT));
|
|
|
|
yearMStringView[1]->MoveTo(Bounds().right-yearMStringView[1]->Bounds().right,5);
|
|
yearStringView->MoveTo(yearMStringView[1]->Frame().left-yearStringView->Bounds().right,5);
|
|
yearMStringView[0]->MoveTo(yearStringView->Frame().left-yearMStringView[0]->Bounds().right,5);
|
|
|
|
monthStringView->MoveTo((yearMStringView[0]->Frame().left-monthStringView->Bounds().right)/2,5);
|
|
monthMStringView[0]->MoveTo(monthStringView->Frame().left-monthMStringView[0]->Bounds().right,5);
|
|
monthMStringView[1]->MoveTo(monthStringView->Frame().right,5);
|
|
|
|
which_focused=2; // days of month
|
|
|
|
// Bitmap for the dates
|
|
Bmp=new BBitmap(Bounds(),B_RGB32,true);
|
|
BmpView=new BView(Bmp->Bounds(),"BV",0,B_WILL_DRAW);
|
|
Bmp->AddChild(BmpView);
|
|
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
BmpView->FillRect(BmpView->Frame());
|
|
BmpView->SetHighColor(255,255,255);
|
|
BRect bmpRect(Bounds());
|
|
bmpRect.top = yearStringView->Frame().bottom + 2;
|
|
bmpRect.bottom = todayStringView->Frame().top - 5;
|
|
BmpView->FillRect(bmpRect);
|
|
|
|
BmpView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT));
|
|
BmpView->StrokeLine(BPoint(0,bmpRect.top), BPoint(BmpView->Bounds().right,bmpRect.top));
|
|
BmpView->StrokeLine(BPoint(0,bmpRect.bottom), BPoint(BmpView->Bounds().right,bmpRect.bottom));
|
|
BmpView->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
|
|
|
float y=yearStringView->Frame().bottom+h_cell;
|
|
float x=0;
|
|
for(int i=0;i<7;i++)
|
|
{
|
|
BmpView->DrawString(weekdayNames[i],BPoint(x+(w_cell-StringWidth(weekdayNames[i]))/2,y));
|
|
x+=w_cell;
|
|
}
|
|
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
|
|
DrawMonth();
|
|
}
|
|
|
|
|
|
void MonthView::Draw(BRect r)
|
|
{
|
|
Window()->Lock();
|
|
DrawBitmap(Bmp, BPoint(0,0));
|
|
Window()->Unlock();
|
|
}
|
|
|
|
|
|
void MonthView::DrawMonth()
|
|
{
|
|
Bmp->Lock();
|
|
|
|
float y=yearStringView->Frame().bottom+h_cell;
|
|
float x=0;
|
|
|
|
if(NewMonth)
|
|
{
|
|
BmpView->SetHighColor(255,255,255);
|
|
BmpView->FillRect(BRect(0,y+1, BmpView->Bounds().right,todayStringView->Frame().top - 6));
|
|
BmpView->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
|
BmpView->SetLowColor(255,255,255);
|
|
NewMonth=false;
|
|
}
|
|
|
|
int byear=cyear; // base year
|
|
if(tyear<byear) byear=tyear;
|
|
|
|
int day1=0, m=0, k=byear;
|
|
|
|
while(k<cyear)
|
|
{
|
|
day1++;
|
|
|
|
if(k%4==0) // leap year?
|
|
if((k%100!=0) || (k%400==0)) day1++; // yes
|
|
|
|
k++;
|
|
}
|
|
while(++m<cmonth)
|
|
{
|
|
day1+=(monthDays[m-1]-28);
|
|
if(m==2) if((cyear%4)==0) if((cyear%100!=0) || (cyear%400==0)) day1++;
|
|
}
|
|
day1++; // day1 is number of 1st day of chosen month in chosen year
|
|
day1=day1%7;
|
|
|
|
int day2=0;
|
|
m=0;
|
|
k=byear;
|
|
while(k<tyear)
|
|
{
|
|
day2++;
|
|
if((k%4)==0) if((k%100!=0) || (k%400==0)) day2++;
|
|
k++;
|
|
}
|
|
while(++m<tmonth)
|
|
{
|
|
day2+=(monthDays[m-1]-28);
|
|
if(m==2) if((tyear%4)==0) if((tyear%100!=0) || (tyear%400==0)) day2++;
|
|
}
|
|
day2+=tday; // day2 - number of today's day in today's year
|
|
day2=day2%7;
|
|
|
|
k=(twday==0) ? 6 : twday-1;
|
|
|
|
k=k-day2+day1;
|
|
while(k<0) k+=7;
|
|
k=k%7;
|
|
cwday1=k;
|
|
|
|
x=w_cell*k+1;
|
|
y+=h_cell;
|
|
|
|
int qu_days=monthDays[cmonth-1]; // quantity of days in month
|
|
|
|
if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29;
|
|
|
|
BString s;
|
|
int t=0;
|
|
while(t<qu_days)
|
|
{
|
|
t++;
|
|
|
|
s<<t;
|
|
|
|
if(cyear==tyear) if(cmonth==tmonth) if(t==tday) BmpView->SetHighColor(236,0,0,0);
|
|
BmpView->DrawString(s.String(),BPoint(x+(w_cell-StringWidth(s.String()))/2,y));
|
|
if(cyear==tyear) if(cmonth==tmonth) if(t==tday) BmpView->SetHighColor(0,0,0,0);
|
|
|
|
if(t==cday)
|
|
{
|
|
cwday=k;
|
|
if(which_focused==2) BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
else
|
|
// BmpView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT));
|
|
BmpView->SetHighColor(255,255,255);
|
|
cursor.Set(x,y-h_cell+5,x+w_cell-1,y+4);
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0,0);
|
|
}
|
|
|
|
x+=w_cell;
|
|
k++;
|
|
s.SetTo("");
|
|
|
|
if(k==7)
|
|
{
|
|
k=0;
|
|
y+=h_cell;
|
|
x=1;
|
|
}
|
|
}
|
|
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
Draw(Bounds());
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
void MonthView::KeyDown(const char *bytes, int32 numBytes)
|
|
{
|
|
switch(bytes[0])
|
|
{
|
|
case B_TAB:
|
|
{
|
|
Bmp->Lock();
|
|
switch(which_focused)
|
|
{
|
|
case 0: // months
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
BmpView->StrokeLine(BPoint(monthMStringView[0]->Frame().left,
|
|
monthMStringView[0]->Frame().bottom+1),
|
|
BPoint(monthMStringView[1]->Frame().right,
|
|
monthMStringView[1]->Frame().bottom+1));
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
case 1: // years
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
BmpView->StrokeLine(BPoint(yearMStringView[0]->Frame().left,
|
|
yearMStringView[0]->Frame().bottom+1),
|
|
BPoint(yearMStringView[1]->Frame().right,
|
|
yearMStringView[1]->Frame().bottom+1));
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
case 2: // days of month
|
|
{
|
|
BmpView->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_3_TINT));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
case 3: // today
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
BmpView->StrokeLine(BPoint(todayStringView->Frame().left,
|
|
todayStringView->Frame().bottom+1),
|
|
BPoint(todayStringView->Frame().right,
|
|
todayStringView->Frame().bottom+1));
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// changing which_focused
|
|
if(modifiers() & B_SHIFT_KEY)
|
|
{
|
|
if(which_focused==0)
|
|
which_focused=3;
|
|
else which_focused--;
|
|
}
|
|
else // simply Tab
|
|
{
|
|
if(which_focused==3)
|
|
which_focused=0;
|
|
else which_focused++;
|
|
}
|
|
|
|
// drawing with new which_focused
|
|
switch(which_focused)
|
|
{
|
|
case 0: // months
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeLine(BPoint(monthMStringView[0]->Frame().left,
|
|
monthMStringView[0]->Frame().bottom+1),
|
|
BPoint(monthMStringView[1]->Frame().right,
|
|
monthMStringView[1]->Frame().bottom+1));
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
case 1: // years
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeLine(BPoint(yearMStringView[0]->Frame().left,
|
|
yearMStringView[0]->Frame().bottom+1),
|
|
BPoint(yearMStringView[1]->Frame().right,
|
|
yearMStringView[1]->Frame().bottom+1));
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
case 2: // days of month
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
case 3: // today
|
|
{
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeLine(BPoint(todayStringView->Frame().left,
|
|
todayStringView->Frame().bottom+1),
|
|
BPoint(todayStringView->Frame().right,
|
|
todayStringView->Frame().bottom+1));
|
|
BmpView->SetHighColor(0,0,0);
|
|
break;
|
|
}
|
|
}
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
Draw(Bounds());
|
|
break;
|
|
} // B_TAB
|
|
|
|
case B_DOWN_ARROW:
|
|
{
|
|
if(which_focused==0) // month
|
|
{
|
|
BMessage msg('MON0');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==1) // year
|
|
{
|
|
BMessage msg('YEA0');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==2) // days of month
|
|
{
|
|
int qu_days=monthDays[cmonth-1];
|
|
if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29;
|
|
if((cday+7)<=qu_days)
|
|
{
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(255,255,255);
|
|
BmpView->StrokeRect(cursor);
|
|
cursor.OffsetBySelf(0, h_cell);
|
|
cday+=7;
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0);
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
Draw(Bounds());
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case B_UP_ARROW:
|
|
{
|
|
// Test whether Ctrl+UpArrow is pressed
|
|
if(modifiers() & B_CONTROL_KEY)
|
|
Window()->PostMessage(B_QUIT_REQUESTED);
|
|
else
|
|
{
|
|
if(which_focused==0) // month
|
|
{
|
|
BMessage msg('MON1');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==1) // year
|
|
{
|
|
BMessage msg('YEA1');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==2) // days of month
|
|
{
|
|
if((cday-7)>=1)
|
|
{
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(255,255,255);
|
|
BmpView->StrokeRect(cursor);
|
|
cursor.OffsetBySelf(0, -h_cell);
|
|
cday-=7;
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0);
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
Draw(Bounds());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case B_LEFT_ARROW:
|
|
{
|
|
if(which_focused==0) // month
|
|
{
|
|
BMessage msg('MON0');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==1) // year
|
|
{
|
|
BMessage msg('YEA0');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==2) // days of month
|
|
{
|
|
if(cday>1)
|
|
{
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(255,255,255);
|
|
BmpView->StrokeRect(cursor);
|
|
if(cwday>0) // by dates no matter of day of week
|
|
{
|
|
cursor.OffsetBySelf(-w_cell,0);
|
|
cwday--;
|
|
}
|
|
else // cwday==0
|
|
{
|
|
cursor.OffsetBySelf(w_cell*6,-h_cell);
|
|
cwday=6;
|
|
}
|
|
cday--;
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0);
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
Draw(Bounds());
|
|
}
|
|
else // 1st of month, go month before
|
|
{
|
|
if(cyear>first_year || cmonth>1) // one can go
|
|
{
|
|
int cm=(cmonth==1) ? 12 : cmonth-1;
|
|
int qu_days=monthDays[cm-1];
|
|
if(cm==2) if(cyear%4==0)
|
|
if((cyear%100!=0) || (cyear%400==0)) qu_days=29;
|
|
// it is correct not to pay attention to year changing
|
|
// because if we moved to february then year was not changed
|
|
// but if month is other then february
|
|
// then it has the same number of days every year.
|
|
cday=qu_days;
|
|
|
|
BMessage msg('MON0');
|
|
MessageReceived(&msg); // here month, cwday and year (if needed) will be changed
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case B_RIGHT_ARROW:
|
|
{
|
|
if(which_focused==0) // month
|
|
{
|
|
BMessage msg('MON1');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==1) // year
|
|
{
|
|
BMessage msg('YEA1');
|
|
MessageReceived(&msg);
|
|
}
|
|
else if(which_focused==2) // days of month
|
|
{
|
|
int qu_days=monthDays[cmonth-1];
|
|
if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29;
|
|
if(cday<qu_days)
|
|
{
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(255,255,255);
|
|
BmpView->StrokeRect(cursor);
|
|
if(cwday<6) // by dates no matter of day of week
|
|
{
|
|
cursor.OffsetBySelf(w_cell,0);
|
|
cwday++;
|
|
}
|
|
else // cwday==6
|
|
{
|
|
cursor.OffsetBySelf(-w_cell*6,h_cell);
|
|
cwday=0;
|
|
}
|
|
cday++;
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(0,0,0);
|
|
BmpView->Sync();
|
|
Bmp->Unlock();
|
|
Draw(Bounds());
|
|
}
|
|
else // last of month, go next month
|
|
{
|
|
if(cyear<last_year || cmonth<12) // one can go
|
|
{
|
|
cday=1;
|
|
BMessage msg('MON1');
|
|
MessageReceived(&msg); // here month, cwday and year (if needed) will be changed
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case B_ESCAPE:
|
|
{
|
|
Window()->PostMessage(B_QUIT_REQUESTED);
|
|
break;
|
|
}
|
|
|
|
case B_ENTER:
|
|
case B_SPACE:
|
|
{
|
|
if(which_focused==2)
|
|
{
|
|
// here it is needed to send dayPressed (==cwday), cyear, cmonth
|
|
// to window and leave
|
|
BMessage *msg=new BMessage('MVME');
|
|
msg->AddInt32("day",cday);
|
|
msg->AddInt32("month",cmonth);
|
|
msg->AddInt32("year",cyear);
|
|
Window()->PostMessage(msg);
|
|
}
|
|
else if(which_focused==3)
|
|
{
|
|
BMessage msg('TODA');
|
|
MessageReceived(&msg);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
BView::KeyDown(bytes, numBytes);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////
|
|
void MonthView::MessageReceived(BMessage *msg)
|
|
{
|
|
switch(msg->what)
|
|
{
|
|
case 'YEA0': // year before
|
|
{
|
|
if(cyear<=first_year) break;
|
|
cyear--;
|
|
NewMonth=true;
|
|
BString s("");
|
|
if(cyear<10) s.Append("000");
|
|
else if(cyear<100) s.Append("00");
|
|
else if(cyear<1000) s.Append("0");
|
|
s<<cyear;
|
|
yearStringView->SetText(s.String());
|
|
|
|
if(cmonth==2) if(cday==29) // one can do simplier: if cday==29, then make
|
|
// cday=28, because two leap years one after other can't be
|
|
{
|
|
if(cyear%4!=0) cday=28;
|
|
else if(cyear%100==0 && cyear%400!=0) cday=28;
|
|
}
|
|
|
|
DrawMonth();
|
|
break;
|
|
}
|
|
case 'YEA1': // year after
|
|
{
|
|
if(cyear>=last_year) break;
|
|
cyear++;
|
|
NewMonth=true;
|
|
BString s("");
|
|
if(cyear<10) s.Append("000");
|
|
else if(cyear<100) s.Append("00");
|
|
else if(cyear<1000) s.Append("0");
|
|
s<<cyear;
|
|
yearStringView->SetText(s.String());
|
|
|
|
if(cmonth==2) if(cday==29)
|
|
{
|
|
if(cyear%4!=0) cday=28;
|
|
else if(cyear%100==0 && cyear%400!=0) cday=28;
|
|
}
|
|
|
|
DrawMonth();
|
|
break;
|
|
}
|
|
case 'MON0': // month before
|
|
{
|
|
if(cmonth>1) cmonth--;
|
|
else if(cyear>first_year)
|
|
{
|
|
cmonth=12;
|
|
cyear--;
|
|
|
|
BString s("");
|
|
if(cyear<10) s.Append("000");
|
|
else if(cyear<100) s.Append("00");
|
|
else if(cyear<1000) s.Append("0");
|
|
s<<cyear;
|
|
yearStringView->SetText(s.String());
|
|
}
|
|
else break; // nothing is changed
|
|
|
|
NewMonth=true;
|
|
monthStringView->SetText(monthNames[cmonth-1]);
|
|
|
|
if(cmonth==2)
|
|
{
|
|
int tmpday=28;
|
|
if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) tmpday=29;
|
|
if(cday>tmpday) cday=tmpday;
|
|
}
|
|
else if(cday>monthDays[cmonth-1]) cday=monthDays[cmonth-1];
|
|
|
|
DrawMonth();
|
|
break;
|
|
}
|
|
case 'MON1': // month after
|
|
{
|
|
if(cmonth<12) cmonth++;
|
|
else if(cyear<last_year)
|
|
{
|
|
cmonth=1;
|
|
cyear++;
|
|
|
|
BString s("");
|
|
if(cyear<10) s.Append("000");
|
|
else if(cyear<100) s.Append("00");
|
|
else if(cyear<1000) s.Append("0");
|
|
s<<cyear;
|
|
yearStringView->SetText(s.String());
|
|
}
|
|
else break; // nothing is changed
|
|
|
|
NewMonth=true;
|
|
monthStringView->SetText(monthNames[cmonth-1]);
|
|
|
|
if(cmonth==2)
|
|
{
|
|
int tmpday=28;
|
|
if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) tmpday=29;
|
|
if(cday>tmpday) cday=tmpday;
|
|
}
|
|
else if(cday>monthDays[cmonth-1]) cday=monthDays[cmonth-1];
|
|
|
|
DrawMonth();
|
|
break;
|
|
}
|
|
case 'TODA': // to place to today's date
|
|
{
|
|
if(tyear<first_year || tyear>last_year) break;
|
|
|
|
NewMonth=true;
|
|
|
|
cyear=tyear;
|
|
cmonth=tmonth;
|
|
cday=tday;
|
|
|
|
BString s("");
|
|
if(cyear<10) s.Append("000");
|
|
else if(cyear<100) s.Append("00");
|
|
else if(cyear<1000) s.Append("0");
|
|
s<<cyear;
|
|
yearStringView->SetText(s.String());
|
|
monthStringView->SetText(monthNames[cmonth-1]);
|
|
|
|
DrawMonth();
|
|
break;
|
|
}
|
|
default:
|
|
BView::MessageReceived(msg);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////
|
|
void MonthView::MouseDown(BPoint p)
|
|
{
|
|
// It's necessary to define whether mouse cursor is on one of dates
|
|
BRect r;
|
|
|
|
int k=cwday1;
|
|
float x=w_cell*k+1;
|
|
float y=yearStringView->Frame().bottom+h_cell+h_cell;
|
|
|
|
int qu_days=monthDays[cmonth-1]; // quantity of days in month
|
|
|
|
if(cmonth==2) if(cyear%4==0) if((cyear%100!=0) || (cyear%400==0)) qu_days=29;
|
|
|
|
bool flag=false; // whether mouse is pressed just on date
|
|
int t=0;
|
|
while(t<qu_days)
|
|
{
|
|
t++;
|
|
r.Set(x,y-h_cell+5,x+w_cell-1,y+4);
|
|
|
|
if(r.Contains(p))
|
|
{
|
|
flag=true;
|
|
dayPressed=t;
|
|
cursorPressed.Set(r.left,r.top,r.right,r.bottom);
|
|
MousePressed=true;
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursorPressed);
|
|
Bmp->Unlock();
|
|
Invalidate();
|
|
break; // exit while
|
|
}
|
|
|
|
x+=w_cell;
|
|
k++;
|
|
|
|
if(k==7)
|
|
{
|
|
k=0;
|
|
y+=h_cell;
|
|
x=1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MonthView::MouseUp(BPoint p)
|
|
{
|
|
if(!MousePressed) return;
|
|
|
|
if(cursorPressed.Contains(p))
|
|
{
|
|
// here it is needed to send dayPressed, cyear, cmonth
|
|
// to window and leave
|
|
BMessage *msg=new BMessage('MVME');
|
|
msg->AddInt32("day",dayPressed);
|
|
msg->AddInt32("month",cmonth);
|
|
msg->AddInt32("year",cyear);
|
|
Window()->PostMessage(msg);
|
|
}
|
|
else
|
|
{
|
|
Bmp->Lock();
|
|
BmpView->SetHighColor(255,255,255);
|
|
BmpView->StrokeRect(cursorPressed);
|
|
BmpView->SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
|
|
BmpView->StrokeRect(cursor);
|
|
Bmp->Unlock();
|
|
Invalidate();
|
|
MousePressed=false;
|
|
}
|
|
}
|
|
|
|
|
|
void MonthView::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg)
|
|
{
|
|
BPoint point;
|
|
uint32 buttons;
|
|
GetMouse(&point,&buttons);
|
|
|
|
if(transit==B_ENTERED_VIEW)
|
|
{
|
|
if( (buttons & B_PRIMARY_MOUSE_BUTTON)==0 &&
|
|
(buttons & B_SECONDARY_MOUSE_BUTTON)==0 &&
|
|
(buttons & B_PRIMARY_MOUSE_BUTTON)==0 )
|
|
MousePressed = false;
|
|
else
|
|
MousePressed = true;
|
|
}
|
|
|
|
if(transit==B_EXITED_VIEW || transit==B_OUTSIDE_VIEW)
|
|
MouseUp(Bounds().LeftTop());
|
|
}
|