* Allow use of unicode character in time view
* Some support for languages having an order different than H:M:S:AM (like chinese). Does not seem to work too well, but I can't spot what I missed * API to get the infos about the type of each field in a time format git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37517 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,6 +20,14 @@ enum {
|
||||
B_US
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
B_INVALID = B_BAD_DATA,
|
||||
B_AM_PM = 0,
|
||||
B_HOUR,
|
||||
B_MINUTE,
|
||||
B_SECOND
|
||||
} BDateField;
|
||||
|
||||
|
||||
class BCountry {
|
||||
public:
|
||||
@@ -44,7 +52,9 @@ class BCountry {
|
||||
virtual void FormatTime(BString* string, time_t time,
|
||||
bool longFormat);
|
||||
status_t FormatTime(BString* string, int*& fieldPositions,
|
||||
int& fieldCount, time_t time, bool LongFormat);
|
||||
int& fieldCount, time_t time, bool longFormat);
|
||||
status_t TimeFields(BDateField*& fields, int& fieldCount,
|
||||
bool longFormat);
|
||||
|
||||
bool DateFormat(BString&, bool longFormat) const;
|
||||
void SetDateFormat(const char* formatString,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <Country.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
@@ -239,6 +240,61 @@ BCountry::FormatTime(BString* string, int*& fieldPositions, int& fieldCount,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCountry::TimeFields(BDateField*& fields, int& fieldCount, bool longFormat)
|
||||
{
|
||||
fields = NULL;
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
ICU_VERSION::DateFormat* timeFormatter;
|
||||
ICU_VERSION::FieldPositionIterator positionIterator;
|
||||
timeFormatter = longFormat ? fICULongTimeFormatter : fICUShortTimeFormatter;
|
||||
UnicodeString ICUString;
|
||||
time_t now;
|
||||
ICUString = timeFormatter->format((UDate)time(&now) * 1000, ICUString,
|
||||
&positionIterator, error);
|
||||
|
||||
if (error != U_ZERO_ERROR)
|
||||
return B_ERROR;
|
||||
|
||||
ICU_VERSION::FieldPosition field;
|
||||
std::vector<int> fieldPosStorage;
|
||||
fieldCount = 0;
|
||||
while (positionIterator.next(field)) {
|
||||
fieldPosStorage.push_back(field.getField());
|
||||
fieldCount ++;
|
||||
}
|
||||
|
||||
fields = (BDateField*) malloc(fieldCount * sizeof(BDateField));
|
||||
|
||||
for (int i = 0 ; i < fieldCount ; i++ ) {
|
||||
switch (fieldPosStorage[i]) {
|
||||
case UDAT_HOUR_OF_DAY1_FIELD:
|
||||
case UDAT_HOUR_OF_DAY0_FIELD:
|
||||
case UDAT_HOUR1_FIELD:
|
||||
case UDAT_HOUR0_FIELD:
|
||||
fields[i] = B_HOUR;
|
||||
break;
|
||||
case UDAT_MINUTE_FIELD:
|
||||
fields[i] = B_MINUTE;
|
||||
break;
|
||||
case UDAT_SECOND_FIELD:
|
||||
fields[i] = B_SECOND;
|
||||
break;
|
||||
case UDAT_AM_PM_FIELD:
|
||||
fields[i] = B_AM_PM;
|
||||
break;
|
||||
default:
|
||||
std::cout << "invalid field id " << fieldPosStorage[i]
|
||||
<< std::endl;
|
||||
fields[i] = B_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BCountry::DateFormat(BString& format, bool longFormat) const
|
||||
{
|
||||
|
||||
@@ -115,15 +115,13 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
||||
country->FormatTime(&text, fieldPositions, fieldCount, time, true);
|
||||
// TODO : this should be cached somehow to not redo it for each field
|
||||
|
||||
if (index * 2 + 1 > fieldCount) {
|
||||
if (index * 2 + 1 >= fieldCount) {
|
||||
free(fieldPositions);
|
||||
return;
|
||||
}
|
||||
|
||||
BString field;
|
||||
// TODO : the following calculations assume chars are 8-bit. The
|
||||
// fieldPositions are character index, not byte index.
|
||||
field.SetTo(text.String()+fieldPositions[index * 2],
|
||||
text.CopyCharsInto(field, fieldPositions[index * 2],
|
||||
fieldPositions[index * 2 + 1] - fieldPositions[index * 2]);
|
||||
|
||||
free(fieldPositions);
|
||||
@@ -136,8 +134,7 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
||||
|
||||
SetHighColor(0, 0, 0, 255);
|
||||
FillRect(bounds, B_SOLID_LOW);
|
||||
DrawString(field.String(), bounds.LeftBottom() - offset);
|
||||
|
||||
DrawString(field, bounds.LeftBottom() - offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -169,9 +166,7 @@ TTimeEdit::DrawSeparator(uint32 index)
|
||||
}
|
||||
|
||||
BString field;
|
||||
// TODO : the following calculations assume chars are 8-bit. The
|
||||
// fieldPositions are character index, not byte index.
|
||||
field.SetTo(text.String()+fieldPositions[index * 2 + 1],
|
||||
text.CopyCharsInto(field, fieldPositions[index * 2 + 1],
|
||||
fieldPositions[index * 2 + 2] - fieldPositions[index * 2 + 1]);
|
||||
|
||||
free(fieldPositions);
|
||||
@@ -274,14 +269,27 @@ TTimeEdit::BuildDispatch(BMessage *message)
|
||||
|
||||
message->AddBool("time", true);
|
||||
|
||||
BDateField* dateFormat;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(dateFormat, fieldCount, true);
|
||||
if (fFocus > fieldCount) {
|
||||
free(dateFormat);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 index = 0; index < fSectionList->CountItems() -1; ++index) {
|
||||
uint32 data = _SectionValue(index);
|
||||
|
||||
if (fFocus == index)
|
||||
data = fHoldValue;
|
||||
|
||||
message->AddInt32(fields[index], data);
|
||||
if (dateFormat[index] < 3)
|
||||
message->AddInt32(fields[dateFormat[index]], data);
|
||||
}
|
||||
|
||||
free(dateFormat);
|
||||
}
|
||||
|
||||
|
||||
@@ -289,9 +297,17 @@ void
|
||||
TTimeEdit::_CheckRange()
|
||||
{
|
||||
int32 value = fHoldValue;
|
||||
switch (fFocus) {
|
||||
case 0:
|
||||
// hour
|
||||
BDateField* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(fields, fieldCount, true);
|
||||
if (fFocus > fieldCount) {
|
||||
free(fields);
|
||||
return;
|
||||
}
|
||||
switch (fields[fFocus]) {
|
||||
case B_HOUR:
|
||||
if (value > 23)
|
||||
value = 0;
|
||||
else if (value < 0)
|
||||
@@ -300,8 +316,7 @@ TTimeEdit::_CheckRange()
|
||||
fTime.SetTime(value, fTime.Minute(), fTime.Second());
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// minute
|
||||
case B_MINUTE:
|
||||
if (value> 59)
|
||||
value = 0;
|
||||
else if (value < 0)
|
||||
@@ -310,8 +325,7 @@ TTimeEdit::_CheckRange()
|
||||
fTime.SetTime(fTime.Hour(), value, fTime.Second());
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// second
|
||||
case B_SECOND:
|
||||
if (value > 59)
|
||||
value = 0;
|
||||
else if (value < 0)
|
||||
@@ -320,8 +334,7 @@ TTimeEdit::_CheckRange()
|
||||
fTime.SetTime(fTime.Hour(), fTime.Minute(), value);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// AM/PM
|
||||
case B_AM_PM:
|
||||
value = fTime.Hour();
|
||||
if (value < 13)
|
||||
value += 12;
|
||||
@@ -335,9 +348,12 @@ TTimeEdit::_CheckRange()
|
||||
break;
|
||||
|
||||
default:
|
||||
free(fields);
|
||||
return;
|
||||
}
|
||||
|
||||
free(fields);
|
||||
|
||||
fHoldValue = value;
|
||||
Invalidate(Bounds());
|
||||
}
|
||||
@@ -347,29 +363,37 @@ bool
|
||||
TTimeEdit::_IsValidDoubleDigi(int32 value)
|
||||
{
|
||||
bool isInRange = false;
|
||||
switch (fFocus) {
|
||||
case 0:
|
||||
// hour
|
||||
BDateField* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(fields, fieldCount, true);
|
||||
if (fFocus > fieldCount) {
|
||||
free(fields);
|
||||
return false;
|
||||
}
|
||||
switch (fields[fFocus]) {
|
||||
case B_HOUR:
|
||||
if (value <= 23)
|
||||
isInRange = true;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// minute
|
||||
case B_MINUTE:
|
||||
if (value <= 59)
|
||||
isInRange = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// second
|
||||
case B_SECOND:
|
||||
if (value <= 59)
|
||||
isInRange = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
free(fields);
|
||||
return isInRange;
|
||||
}
|
||||
|
||||
free(fields);
|
||||
return isInRange;
|
||||
}
|
||||
|
||||
@@ -378,16 +402,25 @@ int32
|
||||
TTimeEdit::_SectionValue(int32 index) const
|
||||
{
|
||||
int32 value;
|
||||
switch (index) {
|
||||
case 0:
|
||||
BDateField* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(fields, fieldCount, true);
|
||||
if (index > fieldCount) {
|
||||
free(fields);
|
||||
return 0;
|
||||
}
|
||||
switch (fields[index]) {
|
||||
case B_HOUR:
|
||||
value = fTime.Hour();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case B_MINUTE:
|
||||
value = fTime.Minute();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case B_SECOND:
|
||||
value = fTime.Second();
|
||||
break;
|
||||
|
||||
@@ -396,6 +429,7 @@ TTimeEdit::_SectionValue(int32 index) const
|
||||
break;
|
||||
}
|
||||
|
||||
free(fields);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user