* 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
};
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,
+56
View File
@@ -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
{
+64 -30
View File
@@ -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;
}