Largish overhaul of the DateTimeEdit-view in the Time preflet:
* instead of fetching the field data every time something needs to be drawn, we now fetch all the data whenever the date or time changes - simpler and faster, too * adjusted date layout to match time layout, i.e. left-adjusted * lots of cleanup git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38160 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
* Adrien Destugues <[email protected]>
|
* Adrien Destugues <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "DateTimeEdit.h"
|
#include "DateTimeEdit.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -27,15 +28,20 @@ using BPrivate::B_LOCAL_TIME;
|
|||||||
TTimeEdit::TTimeEdit(BRect frame, const char* name, uint32 sections)
|
TTimeEdit::TTimeEdit(BRect frame, const char* name, uint32 sections)
|
||||||
:
|
:
|
||||||
TSectionEdit(frame, name, sections),
|
TSectionEdit(frame, name, sections),
|
||||||
fLastKeyDownTime(0)
|
fLastKeyDownTime(0),
|
||||||
|
fFields(NULL),
|
||||||
|
fFieldCount(0),
|
||||||
|
fFieldPositions(NULL),
|
||||||
|
fFieldPosCount(0)
|
||||||
{
|
{
|
||||||
InitView();
|
InitView();
|
||||||
fTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TTimeEdit::~TTimeEdit()
|
TTimeEdit::~TTimeEdit()
|
||||||
{
|
{
|
||||||
|
free(fFieldPositions);
|
||||||
|
free(fFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,9 +61,9 @@ TTimeEdit::KeyDown(const char* bytes, int32 numBytes)
|
|||||||
|
|
||||||
bigtime_t currentTime = system_time();
|
bigtime_t currentTime = system_time();
|
||||||
if (currentTime - fLastKeyDownTime < 1000000) {
|
if (currentTime - fLastKeyDownTime < 1000000) {
|
||||||
int32 doubleDigi = number + fLastKeyDownInt * 10;
|
int32 doubleDigit = number + fLastKeyDownInt * 10;
|
||||||
if (_IsValidDoubleDigi(doubleDigi))
|
if (_IsValidDoubleDigit(doubleDigit))
|
||||||
number = doubleDigi;
|
number = doubleDigit;
|
||||||
fLastKeyDownTime = 0;
|
fLastKeyDownTime = 0;
|
||||||
} else {
|
} else {
|
||||||
fLastKeyDownTime = currentTime;
|
fLastKeyDownTime = currentTime;
|
||||||
@@ -80,6 +86,10 @@ TTimeEdit::InitView()
|
|||||||
// make sure we call the base class method, as it
|
// make sure we call the base class method, as it
|
||||||
// will create the arrow bitmaps and the section list
|
// will create the arrow bitmaps and the section list
|
||||||
TSectionEdit::InitView();
|
TSectionEdit::InitView();
|
||||||
|
|
||||||
|
fTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
|
||||||
|
_UpdateFields();
|
||||||
|
|
||||||
SetSections(fSectionArea);
|
SetSections(fSectionArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,44 +97,28 @@ TTimeEdit::InitView()
|
|||||||
void
|
void
|
||||||
TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
||||||
{
|
{
|
||||||
TSection* section = NULL;
|
TSection* section = static_cast<TSection*>(fSectionList->ItemAt(index));
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(index));
|
|
||||||
|
|
||||||
if (!section)
|
if (!section)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (fFieldPositions == NULL || index * 2 + 1 > (uint32)fFieldPosCount)
|
||||||
|
return;
|
||||||
|
|
||||||
BRect bounds = section->Frame();
|
BRect bounds = section->Frame();
|
||||||
time_t time = fTime.Time_t();
|
|
||||||
|
|
||||||
SetLowColor(ViewColor());
|
SetLowColor(ViewColor());
|
||||||
BString field;
|
|
||||||
if (hasFocus)
|
if (hasFocus)
|
||||||
SetLowColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
SetLowColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
||||||
|
|
||||||
BString text;
|
BString field;
|
||||||
int* fieldPositions;
|
fText.CopyCharsInto(field, fFieldPositions[index * 2],
|
||||||
int fieldCount;
|
fFieldPositions[index * 2 + 1] - fFieldPositions[index * 2]);
|
||||||
|
|
||||||
BLocale locale;
|
|
||||||
be_locale_roster->GetDefaultLocale(&locale);
|
|
||||||
locale.FormatTime(&text, fieldPositions, fieldCount, time, true);
|
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
|
||||||
|
|
||||||
if (index * 2 + 1 > (uint32)fieldCount) {
|
|
||||||
free(fieldPositions);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.CopyCharsInto(field, fieldPositions[index * 2],
|
|
||||||
fieldPositions[index * 2 + 1] - fieldPositions[index * 2]);
|
|
||||||
|
|
||||||
free(fieldPositions);
|
|
||||||
|
|
||||||
// calc and center text in section rect
|
// calc and center text in section rect
|
||||||
float width = be_plain_font->StringWidth(field);
|
float width = be_plain_font->StringWidth(field);
|
||||||
|
|
||||||
BPoint offset(-((bounds.Width()- width) / 2.0) -1.0,
|
BPoint offset(-((bounds.Width()- width) / 2.0) - 1.0,
|
||||||
bounds.Height() / 2.0 -6.0);
|
bounds.Height() / 2.0 - 6.0);
|
||||||
|
|
||||||
SetHighColor(0, 0, 0, 255);
|
SetHighColor(0, 0, 0, 255);
|
||||||
FillRect(bounds, B_SOLID_LOW);
|
FillRect(bounds, B_SOLID_LOW);
|
||||||
@@ -135,38 +129,22 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
|||||||
void
|
void
|
||||||
TTimeEdit::DrawSeparator(uint32 index)
|
TTimeEdit::DrawSeparator(uint32 index)
|
||||||
{
|
{
|
||||||
TSection* section = NULL;
|
TSection* section = static_cast<TSection*>(fSectionList->ItemAt(index));
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(index));
|
|
||||||
|
|
||||||
if (!section)
|
if (!section)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BRect bounds = section->Frame();
|
if (fFieldPositions == NULL || index * 2 + 2 > (uint32)fFieldPosCount)
|
||||||
float sepWidth = SeparatorWidth();
|
|
||||||
|
|
||||||
BString text;
|
|
||||||
int* fieldPositions;
|
|
||||||
int fieldCount;
|
|
||||||
|
|
||||||
BLocale locale;
|
|
||||||
be_locale_roster->GetDefaultLocale(&locale);
|
|
||||||
time_t time = fTime.Time_t();
|
|
||||||
locale.FormatTime(&text, fieldPositions, fieldCount, time, true);
|
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
|
||||||
|
|
||||||
if (index * 2 + 2 > (uint32)fieldCount) {
|
|
||||||
free(fieldPositions);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
BString field;
|
BString field;
|
||||||
text.CopyCharsInto(field, fieldPositions[index * 2 + 1],
|
fText.CopyCharsInto(field, fFieldPositions[index * 2 + 1],
|
||||||
fieldPositions[index * 2 + 2] - fieldPositions[index * 2 + 1]);
|
fFieldPositions[index * 2 + 2] - fFieldPositions[index * 2 + 1]);
|
||||||
|
|
||||||
free(fieldPositions);
|
|
||||||
|
|
||||||
|
float sepWidth = SeparatorWidth();
|
||||||
|
BRect bounds = section->Frame();
|
||||||
float width = be_plain_font->StringWidth(field);
|
float width = be_plain_font->StringWidth(field);
|
||||||
BPoint offset(-((sepWidth - width) / 2.0) -1.0, bounds.Height() / 2.0 -6.0);
|
BPoint offset(-((sepWidth - width) / 2.0) - 1.0,
|
||||||
|
bounds.Height() / 2.0 - 6.0);
|
||||||
DrawString(field, bounds.RightBottom() - offset);
|
DrawString(field, bounds.RightBottom() - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,16 +157,16 @@ TTimeEdit::SetSections(BRect area)
|
|||||||
|
|
||||||
float sepWidth = SeparatorWidth();
|
float sepWidth = SeparatorWidth();
|
||||||
|
|
||||||
float sep_2 = ceil(sepWidth / fSectionCount +1);
|
float sep_2 = ceil(sepWidth / fSectionCount + 1);
|
||||||
float width = bounds.Width() / fSectionCount -sep_2;
|
float width = bounds.Width() / fSectionCount - sep_2;
|
||||||
bounds.right = bounds.left + (width -sepWidth / fSectionCount);
|
bounds.right = bounds.left + (width - sepWidth / fSectionCount);
|
||||||
|
|
||||||
for (uint32 idx = 0; idx < fSectionCount; idx++) {
|
for (uint32 idx = 0; idx < fSectionCount; idx++) {
|
||||||
fSectionList->AddItem(new TSection(bounds));
|
fSectionList->AddItem(new TSection(bounds));
|
||||||
|
|
||||||
bounds.left = bounds.right + sepWidth;
|
bounds.left = bounds.right + sepWidth;
|
||||||
if (idx == fSectionCount -2)
|
if (idx == fSectionCount - 2)
|
||||||
bounds.right = area.right -1;
|
bounds.right = area.right - 1;
|
||||||
else
|
else
|
||||||
bounds.right = bounds.left + (width - sep_2);
|
bounds.right = bounds.left + (width - sep_2);
|
||||||
}
|
}
|
||||||
@@ -215,11 +193,17 @@ TTimeEdit::SectionFocus(uint32 index)
|
|||||||
void
|
void
|
||||||
TTimeEdit::SetTime(int32 hour, int32 minute, int32 second)
|
TTimeEdit::SetTime(int32 hour, int32 minute, int32 second)
|
||||||
{
|
{
|
||||||
if (fTime.Time().Hour() == hour && fTime.Time().Minute() == minute
|
// make sure to update date upon overflow
|
||||||
&& fTime.Time().Second() == second)
|
if (hour == 0 && minute == 0 && second == 0)
|
||||||
return;
|
fTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
|
||||||
|
|
||||||
fTime.SetTime(BTime(hour, minute, second));
|
fTime.SetTime(BTime(hour, minute, second));
|
||||||
|
|
||||||
|
if (LockLooper()) {
|
||||||
|
_UpdateFields();
|
||||||
|
UnlockLooper();
|
||||||
|
}
|
||||||
|
|
||||||
Invalidate(Bounds());
|
Invalidate(Bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,58 +243,57 @@ TTimeEdit::DoDownPress()
|
|||||||
void
|
void
|
||||||
TTimeEdit::BuildDispatch(BMessage* message)
|
TTimeEdit::BuildDispatch(BMessage* message)
|
||||||
{
|
{
|
||||||
const char* fields[3] = { "hour", "minute", "second" };
|
if (fFocus < 0 || fFocus >= fFieldCount)
|
||||||
|
return;
|
||||||
|
|
||||||
message->AddBool("time", true);
|
message->AddBool("time", true);
|
||||||
|
|
||||||
BDateElement* dateFormat;
|
for (int32 index = 0; index < fSectionList->CountItems() - 1; ++index) {
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetTimeFields(dateFormat, fieldCount, true);
|
|
||||||
if (fFocus > fieldCount) {
|
|
||||||
free(dateFormat);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 index = 0; index < fSectionList->CountItems() -1; ++index) {
|
|
||||||
uint32 data = _SectionValue(index);
|
uint32 data = _SectionValue(index);
|
||||||
|
|
||||||
if (fFocus == index)
|
if (fFocus == index)
|
||||||
data = fHoldValue;
|
data = fHoldValue;
|
||||||
|
|
||||||
switch(dateFormat[index]) {
|
switch (fFields[index]) {
|
||||||
case B_DATE_ELEMENT_HOUR:
|
case B_DATE_ELEMENT_HOUR:
|
||||||
message->AddInt32(fields[0], data);
|
message->AddInt32("hour", data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_DATE_ELEMENT_MINUTE:
|
case B_DATE_ELEMENT_MINUTE:
|
||||||
message->AddInt32(fields[1], data);
|
message->AddInt32("minute", data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_DATE_ELEMENT_SECOND:
|
case B_DATE_ELEMENT_SECOND:
|
||||||
message->AddInt32(fields[2], data);
|
message->AddInt32("second", data);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(dateFormat);
|
|
||||||
|
void
|
||||||
|
TTimeEdit::_UpdateFields()
|
||||||
|
{
|
||||||
|
BLocale locale;
|
||||||
|
be_locale_roster->GetDefaultLocale(&locale);
|
||||||
|
|
||||||
|
time_t time = fTime.Time_t();
|
||||||
|
locale.FormatTime(&fText, fFieldPositions, fFieldPosCount, time, true);
|
||||||
|
locale.GetTimeFields(fFields, fFieldCount, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TTimeEdit::_CheckRange()
|
TTimeEdit::_CheckRange()
|
||||||
{
|
{
|
||||||
int32 value = fHoldValue;
|
if (fFocus < 0 || fFocus >= fFieldCount)
|
||||||
BDateElement* fields;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetTimeFields(fields, fieldCount, true);
|
|
||||||
if (fFocus > fieldCount) {
|
|
||||||
free(fields);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
switch (fields[fFocus]) {
|
int32 value = fHoldValue;
|
||||||
|
switch (fFields[fFocus]) {
|
||||||
case B_DATE_ELEMENT_HOUR:
|
case B_DATE_ELEMENT_HOUR:
|
||||||
if (value > 23)
|
if (value > 23)
|
||||||
value = 0;
|
value = 0;
|
||||||
@@ -356,31 +339,22 @@ TTimeEdit::_CheckRange()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
free(fields);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fields);
|
|
||||||
|
|
||||||
fHoldValue = value;
|
fHoldValue = value;
|
||||||
Invalidate(Bounds());
|
Invalidate(Bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TTimeEdit::_IsValidDoubleDigi(int32 value)
|
TTimeEdit::_IsValidDoubleDigit(int32 value)
|
||||||
{
|
{
|
||||||
bool isInRange = false;
|
if (fFocus < 0 || fFocus >= fFieldCount)
|
||||||
BDateElement* fields;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetTimeFields(fields, fieldCount, true);
|
|
||||||
if (fFocus > fieldCount) {
|
|
||||||
free(fields);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
switch (fields[fFocus]) {
|
bool isInRange = false;
|
||||||
|
switch (fFields[fFocus]) {
|
||||||
case B_DATE_ELEMENT_HOUR:
|
case B_DATE_ELEMENT_HOUR:
|
||||||
if (value <= 23)
|
if (value <= 23)
|
||||||
isInRange = true;
|
isInRange = true;
|
||||||
@@ -397,11 +371,9 @@ TTimeEdit::_IsValidDoubleDigi(int32 value)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
free(fields);
|
break;
|
||||||
return isInRange;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fields);
|
|
||||||
return isInRange;
|
return isInRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,17 +381,11 @@ TTimeEdit::_IsValidDoubleDigi(int32 value)
|
|||||||
int32
|
int32
|
||||||
TTimeEdit::_SectionValue(int32 index) const
|
TTimeEdit::_SectionValue(int32 index) const
|
||||||
{
|
{
|
||||||
int32 value;
|
if (index < 0 || index >= fFieldCount)
|
||||||
BDateElement* fields;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetTimeFields(fields, fieldCount, true);
|
|
||||||
if (index > fieldCount) {
|
|
||||||
free(fields);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
switch (fields[index]) {
|
int32 value;
|
||||||
|
switch (fFields[index]) {
|
||||||
case B_DATE_ELEMENT_HOUR:
|
case B_DATE_ELEMENT_HOUR:
|
||||||
value = fTime.Time().Hour();
|
value = fTime.Time().Hour();
|
||||||
break;
|
break;
|
||||||
@@ -437,7 +403,6 @@ TTimeEdit::_SectionValue(int32 index) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fields);
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,15 +411,21 @@ TTimeEdit::_SectionValue(int32 index) const
|
|||||||
|
|
||||||
|
|
||||||
TDateEdit::TDateEdit(BRect frame, const char* name, uint32 sections)
|
TDateEdit::TDateEdit(BRect frame, const char* name, uint32 sections)
|
||||||
: TSectionEdit(frame, name, sections)
|
:
|
||||||
|
TSectionEdit(frame, name, sections),
|
||||||
|
fFields(NULL),
|
||||||
|
fFieldCount(0),
|
||||||
|
fFieldPositions(NULL),
|
||||||
|
fFieldPosCount(0)
|
||||||
{
|
{
|
||||||
InitView();
|
InitView();
|
||||||
fDate = BDate::CurrentDate(B_LOCAL_TIME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TDateEdit::~TDateEdit()
|
TDateEdit::~TDateEdit()
|
||||||
{
|
{
|
||||||
|
free(fFieldPositions);
|
||||||
|
free(fFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -474,9 +445,9 @@ TDateEdit::KeyDown(const char* bytes, int32 numBytes)
|
|||||||
|
|
||||||
bigtime_t currentTime = system_time();
|
bigtime_t currentTime = system_time();
|
||||||
if (currentTime - fLastKeyDownTime < 1000000) {
|
if (currentTime - fLastKeyDownTime < 1000000) {
|
||||||
int32 doubleDigi = number + fLastKeyDownInt * 10;
|
int32 doubleDigit = number + fLastKeyDownInt * 10;
|
||||||
if (_IsValidDoubleDigi(doubleDigi))
|
if (_IsValidDoubleDigit(doubleDigit))
|
||||||
number = doubleDigi;
|
number = doubleDigit;
|
||||||
fLastKeyDownTime = 0;
|
fLastKeyDownTime = 0;
|
||||||
} else {
|
} else {
|
||||||
fLastKeyDownTime = currentTime;
|
fLastKeyDownTime = currentTime;
|
||||||
@@ -485,21 +456,13 @@ TDateEdit::KeyDown(const char* bytes, int32 numBytes)
|
|||||||
|
|
||||||
// if year add 2000
|
// if year add 2000
|
||||||
|
|
||||||
BDateElement* dateFormat;
|
if (fFields[section] == B_DATE_ELEMENT_YEAR) {
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetDateFields(dateFormat, fieldCount, false);
|
|
||||||
|
|
||||||
if (dateFormat[section] == B_DATE_ELEMENT_YEAR) {
|
|
||||||
int32 oldCentury = int32(fHoldValue / 100) * 100;
|
int32 oldCentury = int32(fHoldValue / 100) * 100;
|
||||||
if (number < 10 && oldCentury == 1900)
|
if (number < 10 && oldCentury == 1900)
|
||||||
number += 70;
|
number += 70;
|
||||||
number += oldCentury;
|
number += oldCentury;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(dateFormat);
|
|
||||||
|
|
||||||
// update display value
|
// update display value
|
||||||
fHoldValue = number;
|
fHoldValue = number;
|
||||||
|
|
||||||
@@ -516,6 +479,10 @@ TDateEdit::InitView()
|
|||||||
// make sure we call the base class method, as it
|
// make sure we call the base class method, as it
|
||||||
// will create the arrow bitmaps and the section list
|
// will create the arrow bitmaps and the section list
|
||||||
TSectionEdit::InitView();
|
TSectionEdit::InitView();
|
||||||
|
|
||||||
|
fDate = BDate::CurrentDate(B_LOCAL_TIME);
|
||||||
|
_UpdateFields();
|
||||||
|
|
||||||
SetSections(fSectionArea);
|
SetSections(fSectionArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,42 +490,23 @@ TDateEdit::InitView()
|
|||||||
void
|
void
|
||||||
TDateEdit::DrawSection(uint32 index, bool hasFocus)
|
TDateEdit::DrawSection(uint32 index, bool hasFocus)
|
||||||
{
|
{
|
||||||
TSection* section = NULL;
|
TSection* section = static_cast<TSection*>(fSectionList->ItemAt(index));
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(index));
|
|
||||||
|
|
||||||
if (!section)
|
if (!section)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BRect bounds = section->Frame();
|
if (fFieldPositions == NULL || index * 2 + 1 > (uint32)fFieldPosCount)
|
||||||
BDateTime dateTime(fDate, BTime());
|
return;
|
||||||
|
|
||||||
SetLowColor(ViewColor());
|
SetLowColor(ViewColor());
|
||||||
BString field;
|
|
||||||
if (hasFocus)
|
if (hasFocus)
|
||||||
SetLowColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
SetLowColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
||||||
|
|
||||||
BString text;
|
BString field;
|
||||||
int* fieldPositions;
|
fText.CopyCharsInto(field, fFieldPositions[index * 2],
|
||||||
int fieldCount;
|
fFieldPositions[index * 2 + 1] - fFieldPositions[index * 2]);
|
||||||
|
|
||||||
BLocale locale;
|
|
||||||
be_locale_roster->GetDefaultLocale(&locale);
|
|
||||||
locale.FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
|
||||||
false);
|
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
|
||||||
|
|
||||||
if (index * 2 + 1 > (uint32)fieldCount) {
|
|
||||||
free(fieldPositions);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.CopyCharsInto(field, fieldPositions[index * 2],
|
|
||||||
fieldPositions[index * 2 + 1] - fieldPositions[index * 2]);
|
|
||||||
|
|
||||||
free(fieldPositions);
|
|
||||||
|
|
||||||
|
|
||||||
// calc and center text in section rect
|
// calc and center text in section rect
|
||||||
|
BRect bounds = section->Frame();
|
||||||
float width = StringWidth(field);
|
float width = StringWidth(field);
|
||||||
BPoint offset(-(bounds.Width() - width) / 2.0 - 1.0,
|
BPoint offset(-(bounds.Width() - width) / 2.0 - 1.0,
|
||||||
(bounds.Height() / 2.0 - 6.0));
|
(bounds.Height() / 2.0 - 6.0));
|
||||||
@@ -572,41 +520,27 @@ TDateEdit::DrawSection(uint32 index, bool hasFocus)
|
|||||||
void
|
void
|
||||||
TDateEdit::DrawSeparator(uint32 index)
|
TDateEdit::DrawSeparator(uint32 index)
|
||||||
{
|
{
|
||||||
if (index == 3)
|
if (index < 0 || index >= 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TSection* section = NULL;
|
TSection* section = static_cast<TSection*>(fSectionList->ItemAt(index));
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(index));
|
if (!section)
|
||||||
BRect bounds = section->Frame();
|
return;
|
||||||
|
|
||||||
float sepWidth = SeparatorWidth();
|
if (fFieldPositions == NULL || index * 2 + 2 > (uint32)fFieldPosCount)
|
||||||
|
|
||||||
SetHighColor(0, 0, 0, 255);
|
|
||||||
|
|
||||||
BString text;
|
|
||||||
int* fieldPositions;
|
|
||||||
int fieldCount;
|
|
||||||
|
|
||||||
BLocale locale;
|
|
||||||
be_locale_roster->GetDefaultLocale(&locale);
|
|
||||||
BDateTime dateTime(fDate, BTime());
|
|
||||||
locale.FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
|
||||||
false);
|
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
|
||||||
|
|
||||||
if (index * 2 + 2 > (uint32)fieldCount) {
|
|
||||||
free(fieldPositions);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
BString field;
|
BString field;
|
||||||
text.CopyCharsInto(field, fieldPositions[index * 2 + 1],
|
fText.CopyCharsInto(field, fFieldPositions[index * 2 + 1],
|
||||||
fieldPositions[index * 2 + 2] - fieldPositions[index * 2 + 1]);
|
fFieldPositions[index * 2 + 2] - fFieldPositions[index * 2 + 1]);
|
||||||
|
|
||||||
free(fieldPositions);
|
|
||||||
|
|
||||||
|
BRect bounds = section->Frame();
|
||||||
float width = be_plain_font->StringWidth(field);
|
float width = be_plain_font->StringWidth(field);
|
||||||
BPoint offset(-((sepWidth - width) / 2.0) -1.0, bounds.Height() / 2.0 -6.0);
|
float sepWidth = SeparatorWidth();
|
||||||
|
BPoint offset(-((sepWidth - width) / 2.0) - 1.0,
|
||||||
|
bounds.Height() / 2.0 - 6.0);
|
||||||
|
|
||||||
|
SetHighColor(0, 0, 0, 255);
|
||||||
DrawString(field, bounds.RightBottom() - offset);
|
DrawString(field, bounds.RightBottom() - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,7 +549,7 @@ void
|
|||||||
TDateEdit::SetSections(BRect area)
|
TDateEdit::SetSections(BRect area)
|
||||||
{
|
{
|
||||||
// TODO : we have to be more clever here, as the fields can move and have
|
// TODO : we have to be more clever here, as the fields can move and have
|
||||||
// different sizes dependin on the locale
|
// different sizes depending on the locale
|
||||||
|
|
||||||
// create sections
|
// create sections
|
||||||
for (uint32 idx = 0; idx < fSectionCount; idx++)
|
for (uint32 idx = 0; idx < fSectionCount; idx++)
|
||||||
@@ -624,25 +558,22 @@ TDateEdit::SetSections(BRect area)
|
|||||||
BRect bounds(area);
|
BRect bounds(area);
|
||||||
float sepWidth = SeparatorWidth();
|
float sepWidth = SeparatorWidth();
|
||||||
|
|
||||||
// year
|
TSection* section = static_cast<TSection*>(fSectionList->ItemAt(0));
|
||||||
TSection* section = NULL;
|
float width = be_plain_font->StringWidth("0000") + 10;
|
||||||
float width = be_plain_font->StringWidth("0000") +6;
|
|
||||||
bounds.right = area.right;
|
|
||||||
bounds.left = bounds.right -width;
|
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(2));
|
|
||||||
section->SetFrame(bounds);
|
|
||||||
|
|
||||||
// day
|
|
||||||
width = be_plain_font->StringWidth("00") +6;
|
|
||||||
bounds.right = bounds.left -sepWidth;
|
|
||||||
bounds.left = bounds.right -width;
|
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(1));
|
|
||||||
section->SetFrame(bounds);
|
|
||||||
|
|
||||||
// month
|
|
||||||
bounds.right = bounds.left - sepWidth;
|
|
||||||
bounds.left = area.left;
|
bounds.left = area.left;
|
||||||
section = static_cast<TSection*> (fSectionList->ItemAt(0));
|
bounds.right = bounds.left + width;
|
||||||
|
section->SetFrame(bounds);
|
||||||
|
|
||||||
|
section = static_cast<TSection*>(fSectionList->ItemAt(1));
|
||||||
|
width = be_plain_font->StringWidth("0000") + 10;
|
||||||
|
bounds.left = bounds.right + sepWidth;
|
||||||
|
bounds.right = bounds.left + width;
|
||||||
|
section->SetFrame(bounds);
|
||||||
|
|
||||||
|
section = static_cast<TSection*>(fSectionList->ItemAt(2));
|
||||||
|
width = be_plain_font->StringWidth("0000") + 10;
|
||||||
|
bounds.left = bounds.right + sepWidth;
|
||||||
|
bounds.right = bounds.left + width;
|
||||||
section->SetFrame(bounds);
|
section->SetFrame(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,10 +598,13 @@ TDateEdit::SectionFocus(uint32 index)
|
|||||||
void
|
void
|
||||||
TDateEdit::SetDate(int32 year, int32 month, int32 day)
|
TDateEdit::SetDate(int32 year, int32 month, int32 day)
|
||||||
{
|
{
|
||||||
if (year == fDate.Year() && month == fDate.Month() && day == fDate.Day())
|
|
||||||
return;
|
|
||||||
|
|
||||||
fDate.SetDate(year, month, day);
|
fDate.SetDate(year, month, day);
|
||||||
|
|
||||||
|
if (LockLooper()) {
|
||||||
|
_UpdateFields();
|
||||||
|
UnlockLooper();
|
||||||
|
}
|
||||||
|
|
||||||
Invalidate(Bounds());
|
Invalidate(Bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,68 +644,57 @@ TDateEdit::DoDownPress()
|
|||||||
void
|
void
|
||||||
TDateEdit::BuildDispatch(BMessage* message)
|
TDateEdit::BuildDispatch(BMessage* message)
|
||||||
{
|
{
|
||||||
const char* fields[3] = { "month", "day", "year" };
|
if (fFocus < 0 || fFocus >= fFieldCount)
|
||||||
|
return;
|
||||||
|
|
||||||
message->AddBool("time", false);
|
message->AddBool("time", false);
|
||||||
|
|
||||||
BDateElement* dateFormat;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetDateFields(dateFormat, fieldCount, false);
|
|
||||||
if (fFocus > fieldCount) {
|
|
||||||
free(dateFormat);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int32 index = 0; index < fSectionList->CountItems(); ++index) {
|
for (int32 index = 0; index < fSectionList->CountItems(); ++index) {
|
||||||
uint32 data = _SectionValue(index);
|
uint32 data = _SectionValue(index);
|
||||||
|
|
||||||
if (fFocus == index)
|
if (fFocus == index)
|
||||||
data = fHoldValue;
|
data = fHoldValue;
|
||||||
|
|
||||||
switch(dateFormat[index]) {
|
switch (fFields[index]) {
|
||||||
case B_DATE_ELEMENT_MONTH:
|
case B_DATE_ELEMENT_MONTH:
|
||||||
message->AddInt32(fields[0], data);
|
message->AddInt32("month", data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_DATE_ELEMENT_DAY:
|
case B_DATE_ELEMENT_DAY:
|
||||||
message->AddInt32(fields[1], data);
|
message->AddInt32("day", data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_DATE_ELEMENT_YEAR:
|
case B_DATE_ELEMENT_YEAR:
|
||||||
message->AddInt32(fields[2], data);
|
message->AddInt32("year", data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(dateFormat);
|
|
||||||
|
void
|
||||||
|
TDateEdit::_UpdateFields()
|
||||||
|
{
|
||||||
|
BLocale locale;
|
||||||
|
be_locale_roster->GetDefaultLocale(&locale);
|
||||||
|
|
||||||
|
time_t time = BDateTime(fDate, BTime()).Time_t();
|
||||||
|
locale.FormatDate(&fText, fFieldPositions, fFieldPosCount, time, false);
|
||||||
|
locale.GetDateFields(fFields, fFieldCount, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TDateEdit::_CheckRange()
|
TDateEdit::_CheckRange()
|
||||||
{
|
{
|
||||||
int32 value = fHoldValue;
|
if (fFocus < 0 || fFocus >= fFieldCount)
|
||||||
BDateElement* fields;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetDateFields(fields, fieldCount, false);
|
|
||||||
if (fFocus > fieldCount) {
|
|
||||||
free(fields);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
switch (fields[fFocus]) {
|
|
||||||
case B_DATE_ELEMENT_MONTH:
|
|
||||||
if (value > 12)
|
|
||||||
value = 1;
|
|
||||||
else if (value < 1)
|
|
||||||
value = 12;
|
|
||||||
|
|
||||||
fDate.SetDate(fDate.Year(), value, fDate.Day());
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
int32 value = fHoldValue;
|
||||||
|
switch (fFields[fFocus]) {
|
||||||
case B_DATE_ELEMENT_DAY:
|
case B_DATE_ELEMENT_DAY:
|
||||||
{
|
{
|
||||||
int32 days = fDate.DaysInMonth();
|
int32 days = fDate.DaysInMonth();
|
||||||
@@ -784,6 +707,15 @@ TDateEdit::_CheckRange()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case B_DATE_ELEMENT_MONTH:
|
||||||
|
if (value > 12)
|
||||||
|
value = 1;
|
||||||
|
else if (value < 1)
|
||||||
|
value = 12;
|
||||||
|
|
||||||
|
fDate.SetDate(fDate.Year(), value, fDate.Day());
|
||||||
|
break;
|
||||||
|
|
||||||
case B_DATE_ELEMENT_YEAR:
|
case B_DATE_ELEMENT_YEAR:
|
||||||
// 2037 is the end of 32-bit UNIX time
|
// 2037 is the end of 32-bit UNIX time
|
||||||
if (value > 2037)
|
if (value > 2037)
|
||||||
@@ -795,53 +727,49 @@ TDateEdit::_CheckRange()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
free(fields);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fields);
|
|
||||||
fHoldValue = value;
|
fHoldValue = value;
|
||||||
Draw(Bounds());
|
Draw(Bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TDateEdit::_IsValidDoubleDigi(int32 value)
|
TDateEdit::_IsValidDoubleDigit(int32 value)
|
||||||
{
|
{
|
||||||
bool isInRange = false;
|
if (fFocus < 0 || fFocus >= fFieldCount)
|
||||||
BDateElement* fields;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetDateFields(fields, fieldCount, false);
|
|
||||||
if (fFocus > fieldCount) {
|
|
||||||
free(fields);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
int32 year = 0;
|
bool isInRange = false;
|
||||||
switch (fields[fFocus]) {
|
switch (fFields[fFocus]) {
|
||||||
case B_DATE_ELEMENT_DAY:
|
case B_DATE_ELEMENT_DAY:
|
||||||
{
|
{
|
||||||
int32 days = fDate.DaysInMonth();
|
int32 days = fDate.DaysInMonth();
|
||||||
if (value <= days)
|
if (value >= 1 && value <= days)
|
||||||
|
isInRange = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_DATE_ELEMENT_MONTH:
|
||||||
|
{
|
||||||
|
if (value >= 1 && value <= 12)
|
||||||
isInRange = true;
|
isInRange = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_DATE_ELEMENT_YEAR:
|
case B_DATE_ELEMENT_YEAR:
|
||||||
{
|
{
|
||||||
year = int32(fHoldValue / 100) * 100 + value;
|
int32 year = int32(fHoldValue / 100) * 100 + value;
|
||||||
if (year <= 2037 && year >= 1970)
|
if (year <= 2037 && year >= 1970)
|
||||||
isInRange = true;
|
isInRange = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
free(fields);
|
break;
|
||||||
return isInRange;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fields);
|
|
||||||
return isInRange;
|
return isInRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,17 +777,15 @@ TDateEdit::_IsValidDoubleDigi(int32 value)
|
|||||||
int32
|
int32
|
||||||
TDateEdit::_SectionValue(int32 index) const
|
TDateEdit::_SectionValue(int32 index) const
|
||||||
{
|
{
|
||||||
int32 value = 0;
|
if (index < 0 || index >= fFieldCount)
|
||||||
BDateElement* fields;
|
|
||||||
int fieldCount;
|
|
||||||
BLocale here;
|
|
||||||
be_locale_roster->GetDefaultLocale(&here);
|
|
||||||
here.GetDateFields(fields, fieldCount, false);
|
|
||||||
if (index > fieldCount) {
|
|
||||||
free(fields);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
switch (fields[index]) {
|
int32 value = 0;
|
||||||
|
switch (fFields[index]) {
|
||||||
|
case B_DATE_ELEMENT_YEAR:
|
||||||
|
value = fDate.Year();
|
||||||
|
break;
|
||||||
|
|
||||||
case B_DATE_ELEMENT_MONTH:
|
case B_DATE_ELEMENT_MONTH:
|
||||||
value = fDate.Month();
|
value = fDate.Month();
|
||||||
break;
|
break;
|
||||||
@@ -869,7 +795,6 @@ TDateEdit::_SectionValue(int32 index) const
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
value = fDate.Year();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#include "SectionEdit.h"
|
#include "SectionEdit.h"
|
||||||
|
|
||||||
#include <DateTime.h>
|
#include <DateTime.h>
|
||||||
|
#include <Locale.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
class TTimeEdit : public TSectionEdit {
|
class TTimeEdit : public TSectionEdit {
|
||||||
@@ -41,14 +43,23 @@ public:
|
|||||||
void SetTime(int32 hour, int32 minute, int32 second);
|
void SetTime(int32 hour, int32 minute, int32 second);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _UpdateFields();
|
||||||
void _CheckRange();
|
void _CheckRange();
|
||||||
bool _IsValidDoubleDigi(int32 value);
|
bool _IsValidDoubleDigit(int32 value);
|
||||||
int32 _SectionValue(int32 index) const;
|
int32 _SectionValue(int32 index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BDateTime fTime;
|
BDateTime fTime;
|
||||||
bigtime_t fLastKeyDownTime;
|
bigtime_t fLastKeyDownTime;
|
||||||
int32 fLastKeyDownInt;
|
int32 fLastKeyDownInt;
|
||||||
|
|
||||||
|
BString fText;
|
||||||
|
|
||||||
|
// TODO: morph the following into a proper class
|
||||||
|
BDateElement* fFields;
|
||||||
|
int fFieldCount;
|
||||||
|
int* fFieldPositions;
|
||||||
|
int fFieldPosCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -75,14 +86,23 @@ public:
|
|||||||
void SetDate(int32 year, int32 month, int32 day);
|
void SetDate(int32 year, int32 month, int32 day);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _UpdateFields();
|
||||||
void _CheckRange();
|
void _CheckRange();
|
||||||
bool _IsValidDoubleDigi(int32 value);
|
bool _IsValidDoubleDigit(int32 value);
|
||||||
int32 _SectionValue(int32 index) const;
|
int32 _SectionValue(int32 index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BDate fDate;
|
BDate fDate;
|
||||||
bigtime_t fLastKeyDownTime;
|
bigtime_t fLastKeyDownTime;
|
||||||
int32 fLastKeyDownInt;
|
int32 fLastKeyDownInt;
|
||||||
|
|
||||||
|
BString fText;
|
||||||
|
|
||||||
|
// TODO: morph the following into a proper class
|
||||||
|
BDateElement* fFields;
|
||||||
|
int fFieldCount;
|
||||||
|
int* fFieldPositions;
|
||||||
|
int fFieldPosCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user