Author: pulkomandy Date: 2010-07-14 18:43:04 +0200 (Wed, 14 Jul 2010) New Revision: 37517 Changeset: http://dev.haiku-os.org/changeset/37517 Modified: haiku/trunk/headers/os/locale/Country.h haiku/trunk/src/kits/locale/Country.cpp haiku/trunk/src/preferences/time/DateTimeEdit.cpp Log: * 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 Modified: haiku/trunk/headers/os/locale/Country.h =================================================================== --- haiku/trunk/headers/os/locale/Country.h 2010-07-14 15:32:00 UTC (rev 37516) +++ haiku/trunk/headers/os/locale/Country.h 2010-07-14 16:43:04 UTC (rev 37517) @@ -20,7 +20,15 @@ B_US }; +typedef enum { + B_INVALID = B_BAD_DATA, + B_AM_PM = 0, + B_HOUR, + B_MINUTE, + B_SECOND +} BDateField; + class BCountry { public: BCountry(const char* languageCode, const char* countryCode); @@ -44,7 +52,9 @@ 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, Modified: haiku/trunk/src/kits/locale/Country.cpp =================================================================== --- haiku/trunk/src/kits/locale/Country.cpp 2010-07-14 15:32:00 UTC (rev 37516) +++ haiku/trunk/src/kits/locale/Country.cpp 2010-07-14 16:43:04 UTC (rev 37517) @@ -8,6 +8,7 @@ #include <Country.h> #include <assert.h> +#include <iostream> #include <stdlib.h> #include <vector> @@ -239,6 +240,61 @@ } +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 { Modified: haiku/trunk/src/preferences/time/DateTimeEdit.cpp =================================================================== --- haiku/trunk/src/preferences/time/DateTimeEdit.cpp 2010-07-14 15:32:00 UTC (rev 37516) +++ haiku/trunk/src/preferences/time/DateTimeEdit.cpp 2010-07-14 16:43:04 UTC (rev 37517) @@ -115,15 +115,13 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ break; default: + free(fields); return; } + free(fields); + fHoldValue = value; Invalidate(Bounds()); } @@ -347,29 +363,37 @@ 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 @@ 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 @@ break; } + free(fields); return value; }