* 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:
Adrien Destugues
2010-07-14 16:43:04 +00:00
parent 1f34e928ac
commit 57500c639c
3 changed files with 131 additions and 31 deletions
+11 -1
View File
@@ -20,6 +20,14 @@ enum {
B_US B_US
}; };
typedef enum {
B_INVALID = B_BAD_DATA,
B_AM_PM = 0,
B_HOUR,
B_MINUTE,
B_SECOND
} BDateField;
class BCountry { class BCountry {
public: public:
@@ -44,7 +52,9 @@ class BCountry {
virtual void FormatTime(BString* string, time_t time, virtual void FormatTime(BString* string, time_t time,
bool longFormat); bool longFormat);
status_t FormatTime(BString* string, int*& fieldPositions, 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; bool DateFormat(BString&, bool longFormat) const;
void SetDateFormat(const char* formatString, void SetDateFormat(const char* formatString,
+56
View File
@@ -8,6 +8,7 @@
#include <Country.h> #include <Country.h>
#include <assert.h> #include <assert.h>
#include <iostream>
#include <stdlib.h> #include <stdlib.h>
#include <vector> #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 bool
BCountry::DateFormat(BString& format, bool longFormat) const BCountry::DateFormat(BString& format, bool longFormat) const
{ {
+64 -30
View File
@@ -115,15 +115,13 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
country->FormatTime(&text, fieldPositions, fieldCount, time, true); country->FormatTime(&text, fieldPositions, fieldCount, time, true);
// TODO : this should be cached somehow to not redo it for each field // 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); free(fieldPositions);
return; return;
} }
BString field; BString field;
// TODO : the following calculations assume chars are 8-bit. The text.CopyCharsInto(field, fieldPositions[index * 2],
// fieldPositions are character index, not byte index.
field.SetTo(text.String()+fieldPositions[index * 2],
fieldPositions[index * 2 + 1] - fieldPositions[index * 2]); fieldPositions[index * 2 + 1] - fieldPositions[index * 2]);
free(fieldPositions); free(fieldPositions);
@@ -136,8 +134,7 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
SetHighColor(0, 0, 0, 255); SetHighColor(0, 0, 0, 255);
FillRect(bounds, B_SOLID_LOW); 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; BString field;
// TODO : the following calculations assume chars are 8-bit. The text.CopyCharsInto(field, fieldPositions[index * 2 + 1],
// fieldPositions are character index, not byte index.
field.SetTo(text.String()+fieldPositions[index * 2 + 1],
fieldPositions[index * 2 + 2] - fieldPositions[index * 2 + 1]); fieldPositions[index * 2 + 2] - fieldPositions[index * 2 + 1]);
free(fieldPositions); free(fieldPositions);
@@ -274,14 +269,27 @@ TTimeEdit::BuildDispatch(BMessage *message)
message->AddBool("time", true); 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) { 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;
message->AddInt32(fields[index], data); if (dateFormat[index] < 3)
message->AddInt32(fields[dateFormat[index]], data);
} }
free(dateFormat);
} }
@@ -289,9 +297,17 @@ void
TTimeEdit::_CheckRange() TTimeEdit::_CheckRange()
{ {
int32 value = fHoldValue; int32 value = fHoldValue;
switch (fFocus) { BDateField* fields;
case 0: int fieldCount;
// hour 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) if (value > 23)
value = 0; value = 0;
else if (value < 0) else if (value < 0)
@@ -300,8 +316,7 @@ TTimeEdit::_CheckRange()
fTime.SetTime(value, fTime.Minute(), fTime.Second()); fTime.SetTime(value, fTime.Minute(), fTime.Second());
break; break;
case 1: case B_MINUTE:
// minute
if (value> 59) if (value> 59)
value = 0; value = 0;
else if (value < 0) else if (value < 0)
@@ -310,8 +325,7 @@ TTimeEdit::_CheckRange()
fTime.SetTime(fTime.Hour(), value, fTime.Second()); fTime.SetTime(fTime.Hour(), value, fTime.Second());
break; break;
case 2: case B_SECOND:
// second
if (value > 59) if (value > 59)
value = 0; value = 0;
else if (value < 0) else if (value < 0)
@@ -320,8 +334,7 @@ TTimeEdit::_CheckRange()
fTime.SetTime(fTime.Hour(), fTime.Minute(), value); fTime.SetTime(fTime.Hour(), fTime.Minute(), value);
break; break;
case 3: case B_AM_PM:
// AM/PM
value = fTime.Hour(); value = fTime.Hour();
if (value < 13) if (value < 13)
value += 12; value += 12;
@@ -335,9 +348,12 @@ TTimeEdit::_CheckRange()
break; break;
default: default:
free(fields);
return; return;
} }
free(fields);
fHoldValue = value; fHoldValue = value;
Invalidate(Bounds()); Invalidate(Bounds());
} }
@@ -347,29 +363,37 @@ bool
TTimeEdit::_IsValidDoubleDigi(int32 value) TTimeEdit::_IsValidDoubleDigi(int32 value)
{ {
bool isInRange = false; bool isInRange = false;
switch (fFocus) { BDateField* fields;
case 0: int fieldCount;
// hour 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) if (value <= 23)
isInRange = true; isInRange = true;
break; break;
case 1: case B_MINUTE:
// minute
if (value <= 59) if (value <= 59)
isInRange = true; isInRange = true;
break; break;
case 2: case B_SECOND:
// second
if (value <= 59) if (value <= 59)
isInRange = true; isInRange = true;
break; break;
default: default:
free(fields);
return isInRange; return isInRange;
} }
free(fields);
return isInRange; return isInRange;
} }
@@ -378,16 +402,25 @@ int32
TTimeEdit::_SectionValue(int32 index) const TTimeEdit::_SectionValue(int32 index) const
{ {
int32 value; int32 value;
switch (index) { BDateField* fields;
case 0: 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(); value = fTime.Hour();
break; break;
case 1: case B_MINUTE:
value = fTime.Minute(); value = fTime.Minute();
break; break;
case 2: case B_SECOND:
value = fTime.Second(); value = fTime.Second();
break; break;
@@ -396,6 +429,7 @@ TTimeEdit::_SectionValue(int32 index) const
break; break;
} }
free(fields);
return value; return value;
} }