initiaql check-in, moved repository -- no-longer a fork of

haikuarchives/yab
This commit is contained in:
Jim
2015-04-13 13:40:27 -07:00
parent 9e266ef95f
commit 3e33065a02
234 changed files with 77847 additions and 1 deletions

620
src/DateTextView.cpp Normal file
View File

@@ -0,0 +1,620 @@
// 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 <Clipboard.h>
#include <InterfaceDefs.h>
#include <Rect.h>
#include <String.h>
#include <TextView.h>
#include <stdlib.h>
#include <time.h>
#define LAST_FORMAT 1 // quantity of formats - 1
#define LAST_DIVIDER 2 // quantity of dividers - 1
class DateTextView: public BTextView
{
public:
DateTextView(int day, int month, int year, uint32 flags, uint32 look);
virtual void Cut(BClipboard *clip);
virtual void KeyDown(const char *bytes, int32 numBytes);
virtual void MakeFocus(bool focused);
virtual void Paste(BClipboard *clip);
virtual void SetEnabled(bool enabled);
void GetDate(int *day, int *month, int *year);
void SetDate(int day, int month, int year);
void SetDate(const char *tdate);
void GetYearRange(int *first_year, int *last_year);
uint32 GetDivider();
void SetDivider(uint32 dvder);
uint32 GetDateFlags();
void SetDateFlags(uint32 flags);
protected:
virtual void DeleteText(int32 start, int32 finish);
private:
virtual bool AcceptsDrop(const BMessage *message);
virtual bool AcceptsPaste(BClipboard *clip);
void DrawDate(int day, int month, int year);
bool VerifyDate(int *day, int *month, int *year);
bool is_ins; // is it necessar to insert symbol
uint32 flags;
char *div[LAST_DIVIDER+1]; // сstrings of dividers
uint32 divider;
bool enabled;
int first_year;
int last_year; // first and last year which control accepts
int textlen; // length of text string (10 or 8 symbols)
uint32 interface; // the same as control variable
};
//////////////////////////////////////////////////////////////////////////
DateTextView::DateTextView(int day, int month, int year,
uint32 flags, uint32 look)
:BTextView(BRect(0,0,110,15),"DateTextViewAViX",
BRect(0,0,110,15),B_FOLLOW_LEFT | B_FOLLOW_TOP,
B_WILL_DRAW | B_NAVIGABLE)
{
enabled=true;
is_ins=false;
interface=look;
div[0]=(char*)".";
div[1]=(char*)"/";
div[2]=(char*)"-";
divider=look & CC_ALL_DIVIDERS;
if(divider>LAST_DIVIDER || divider<0) divider=0; // index of divider
this->flags=(flags & (LAST_FORMAT | CC_SHORT_YEAR | CC_HALF_CENTURY));
if((this->flags & (CC_SHORT_YEAR | CC_HALF_CENTURY))==CC_HALF_CENTURY)
this->flags=this->flags^CC_HALF_CENTURY; // XOR; CC_FULL_YEAR and CC_HALF_CENTURY
// at the same time may not be used
first_year=1;
last_year=9999;
if((this->flags & CC_SHORT_YEAR)==CC_SHORT_YEAR)
{
textlen=8;
// Changing first and last acceptable years
// Working in range of century defined by year variable
if(year<first_year || year>last_year)
{
// Range is set relative to today's year
struct tm *dat;
time_t tmp;
time(&tmp);
dat=localtime(&tmp);
year=dat->tm_year+1900; // today's year
}
first_year=(year/100)*100+1; // dividing with loosing rest
last_year=first_year+99;
if(last_year==10000) last_year--; // full century
if((this->flags & CC_HALF_CENTURY)==CC_HALF_CENTURY)
{
if(year<51 || year>9950)
this->flags=this->flags^CC_HALF_CENTURY; // HALF_CENTURY may nor be set
else
{
if((year%100)>50)
{
first_year+=50;
last_year+=50;
}
else
{
first_year-=50;
last_year-=50;
}
}
}
}
else textlen=10; // length of text string
SetDate(day,month,year);
float width=0;
BString s("");
for(char i='0'; i<='9'; i++)
{
s<<i;
if(StringWidth(s.String())>width) width=StringWidth(s.String());
s.SetTo("");
}
ResizeTo(width*(textlen-2)+StringWidth("/")*2.5, LineHeight()-1);
SetWordWrap(false);
SetMaxBytes(textlen);
SetTextRect(Bounds());
SetDoesUndo(false);
for(int32 i=0;i<256;i++) DisallowChar(i);
for(int32 i='0';i<='9';i++) AllowChar(i);
}
///////////////////////////////////////////////////////
bool DateTextView::AcceptsDrop(const BMessage *message)
{
return false;
}
/////////////////////////////////////////////////
bool DateTextView::AcceptsPaste(BClipboard *clip)
{
return false;
}
////////////////////////////////////////
void DateTextView::Cut(BClipboard *clip)
{
Copy(clip);
}
////////////////////////////////////////////////////////
void DateTextView::DeleteText(int32 start, int32 finish)
{
BTextView::DeleteText(start,finish);
if(is_ins)
{
if(start==2 || start==5) InsertText(div[divider],1,start,NULL);
else InsertText("0",1,start,NULL);
}
}
/////////////////////////////////////////////////////////////
void DateTextView::KeyDown(const char *bytes, int32 numBytes)
{
if(!enabled) if(bytes[0]!=B_TAB) return;
int32 i1,i2;
GetSelection(&i1,&i2);
if(bytes[0]>='0' && bytes[0]<='9')
{
if(i1>(textlen-1)) return; // not to insert after end of string
Select(i1,i1);
if(i1==2 || i1==5)
{
i1++;
Select(i1,i1);
}
DeleteText(i1,i1+1);
BTextView::KeyDown(bytes, numBytes);
}
else if(bytes[0]==B_DELETE)
{
if(i1>(textlen-1)) return; // not to insert after end of string
Select(i1,i1);
is_ins=true; // symbol "0" or divider will be inserted
BTextView::KeyDown(bytes, numBytes);
is_ins=false;
}
else if(bytes[0]==B_BACKSPACE)
{
Select(i1,i1);
is_ins=true;
BTextView::KeyDown(bytes, numBytes);
is_ins=false;
}
else if(bytes[0]==B_TAB)
{
Parent()->KeyDown(bytes, numBytes);
}
else if(bytes[0]==B_DOWN_ARROW)
{
// Is Ctrl+DownArrow pressed?
if(modifiers() & B_CONTROL_KEY)
{
// yes
BMessage msg(myButtonMessage);
Parent()->MessageReceived(&msg);
}
else
BTextView::KeyDown(bytes, numBytes);
}
else
BTextView::KeyDown(bytes, numBytes);
}
///////////////////////////////////////////////
void DateTextView::MakeFocus(bool focused=true)
{
BTextView::MakeFocus(focused);
int day, month, year;
GetDate(&day, &month, &year);
Parent()->Draw(Parent()->Bounds());
}
//////////////////////////////////////////
void DateTextView::Paste(BClipboard *clip)
{
return;
}
///////////////////////////////////////////
void DateTextView::SetEnabled(bool enabled)
{
this->enabled=enabled;
SetFlags(Flags()^B_NAVIGABLE);
MakeEditable(enabled);
BFont font;
rgb_color color;
GetFontAndColor((int32) 0, &font, &color);
color.alpha=0;
if(enabled)
{
SetViewColor(255,255,255,255);
color.red=color.green=color.blue=0;
}
else
{
SetViewColor(239,239,239,255);
color.red=color.green=color.blue=128;
}
SetFontAndColor(&font,B_FONT_ALL,&color);
Invalidate();
}
/////////////////////////////////////////////////////////
void DateTextView::DrawDate(int day, int month, int year)
{
// It is assumed that date is correct
BString s;
s.SetTo("");
if(!((flags & CC_MM_DD_YYYY_FORMAT)==CC_MM_DD_YYYY_FORMAT))
{
if(day<10) s.Append("0");
s<<day;
s.Append(div[divider]);
if(month<10) s.Append("0");
s<<month;
}
else // CC_MM_DD_YYYY_FORMAT
{
if(month<10) s.Append("0");
s<<month;
s.Append(div[divider]);
if(day<10) s.Append("0");
s<<day;
}
s.Append(div[divider]);
if((flags & CC_SHORT_YEAR)==CC_SHORT_YEAR)
{
int year1=year%100;
if(year1<10) s.Append("0");
s<<year1;
}
else // FULL_YEAR
{
if(year<10) s.Append("000");
else if(year<100) s.Append("00");
else if(year<1000) s.Append("0");
s<<year;
}
SetText(s.String());
}
///////////////////////////////////////////////////////////
void DateTextView::GetDate(int *day, int *month, int *year)
{
int mday=*day;
int mmonth=*month;
int myear=*year;
BString s(Text());
char n1[11];
char n2[11];
char n3[11];
s.CopyInto(n1,0,2);
n1[2]='\0';
s.CopyInto(n2,3,2);
n2[2]='\0';
if((flags & CC_SHORT_YEAR)==CC_SHORT_YEAR)
{
s.CopyInto(n3,6,2);
n3[2]='\0';
}
else // FULL_YEAR
{
s.CopyInto(n3,6,4);
n3[4]='\0';
}
if(!((flags & CC_MM_DD_YYYY_FORMAT)==CC_MM_DD_YYYY_FORMAT))
{
mday=atoi(n1);
mmonth=atoi(n2);
}
else
{
mday=atoi(n2);
mmonth=atoi(n1);
}
myear=atoi(n3);
if((flags & CC_SHORT_YEAR)==CC_SHORT_YEAR)
{
if((flags & CC_HALF_CENTURY)==CC_HALF_CENTURY)
{
if(myear<51) myear+=50; else myear-=50;
}
else if(myear==0) myear=100;
myear+=(first_year-1);
}
if(!VerifyDate(&mday,&mmonth,&myear)) SetDate(mday,mmonth,myear);
*day=mday;
*month=mmonth;
*year=myear;
return;
}
////////////////////////////////////////////////////////
void DateTextView::SetDate(int day, int month, int year)
{
int mday=day;
int mmonth=month;
int myear=year;
VerifyDate(&mday, &mmonth, &myear);
DrawDate(mday, mmonth, myear);
}
/////////////////////////////////////////////
void DateTextView::SetDate(const char *tdate)
{
// Almost the same as GetDate. May be to combine them.
// Changes text using current settings of control.
int day;
int month;
int year;
int k;
bool short_year=false;
if((flags & CC_SHORT_YEAR)==CC_SHORT_YEAR) short_year=true;
char n1[3]="00";
char n2[3]="00";
char n3[5]="0000";
if(short_year) n3[2]='\0';
bool zero=false; // was the end of tdate string?
int c=0;
while (!(c==2 || zero))
{
if(tdate[c]=='\0') zero=true;
else n1[c]=tdate[c];
c++;
}
if(zero) goto L1;
if(tdate[2]=='\0') goto L1;
c=0;
while (!(c==2 || zero))
{
if(tdate[c+3]=='\0') zero=true;
else n2[c]=tdate[c+3];
c++;
}
if(zero) goto L1;
if(tdate[5]=='\0') goto L1;
k=short_year ? 2 : 4;
c=0;
while (!(c==k || zero))
{
if(tdate[c+6]=='\0') zero=true;
else n3[c]=tdate[c+6];
c++;
}
L1:
if(!((flags & CC_MM_DD_YYYY_FORMAT)==CC_MM_DD_YYYY_FORMAT))
{
day=atoi(n1);
month=atoi(n2);
}
else
{
day=atoi(n2);
month=atoi(n1);
}
year=atoi(n3);
if(short_year)
{
if((flags & CC_HALF_CENTURY)==CC_HALF_CENTURY)
{
if(year<51) year+=50; else year-=50;
}
else if(year==0) year=100;
year+=(first_year-1);
}
SetDate(day,month,year);
}
//////////////////////////////////////////////////////////////
bool DateTextView::VerifyDate(int *day, int *month, int *year)
{
// Function verifies date to be correct and changes it if it's needed
// Returns true if date was correct (and wasn't changed)
struct tm *dat;
time_t tmp;
time(&tmp);
dat=localtime(&tmp);
bool flag=true; // date is correct
if((flags & CC_SHORT_YEAR)==CC_SHORT_YEAR)
{
if(*year<first_year || *year>last_year)
{
int year1=*year%100;
if((flags & CC_HALF_CENTURY)==CC_HALF_CENTURY)
{
if(year1<51) year1+=50; else year1-=50;
}
else if(year1==0) year1=100;
*year=year1+first_year-1;
flag=false;
}
}
else // FULL_YEAR
{
if(*year<1 || *year>9999)
{
*year=dat->tm_year+1900;
flag=false;
}
}
if(*month<1 || *month>12)
{
*month=dat->tm_mon+1;
flag=false;
}
if(*day<1 || *day>31)
{
*day=dat->tm_mday;
flag=false;
}
if((*month==4 || *month==6 || *month==9 || *month==11) && *day>30)
{
if((*day=dat->tm_mday)>30) *day=30;
flag=false;
}
else if (*month==2)
{
int tmpday;
if((*year)%4==0) // leap year?
{
if((*year)%100==0 && (*year)%400!=0) tmpday=28; // no
else tmpday=29; // yes
}
else tmpday=28;
if(*day>tmpday)
{
if((*day=dat->tm_mday)>tmpday) *day=tmpday;
flag=false;
}
}
return flag;
}
////////////////////////////////////////////////////////////////
void DateTextView::GetYearRange(int *first_year, int *last_year)
{
*first_year=this->first_year;
*last_year=this->last_year;
}
/////////////////////////////////
uint32 DateTextView::GetDivider()
{
return divider;
}
///////////////////////////////////////////
void DateTextView::SetDivider(uint32 dvder)
{
if(dvder<0 || dvder>LAST_DIVIDER) dvder=0;
BString s(Text());
SetText((s.ReplaceAll(div[divider],div[dvder])).String());
this->divider=dvder;
}
///////////////////////////////////
uint32 DateTextView::GetDateFlags()
{
return flags;
}
///////////////////////////////////////////
void DateTextView::SetDateFlags(uint32 fmt)
{
int mday, mmonth, myear;
GetDate(&mday, &mmonth, &myear);
// Blocking changing of parameters of year
// (full/short year, full/half century)
fmt=fmt & 0xFFE7;
if(fmt<0 || fmt>LAST_FORMAT) fmt=0;
flags=fmt | (flags & 0xFFFE); // LAST_FORMAT==1, 1 bit
SetDate(mday, mmonth, myear);
}