WxExtLib - WxMisc.cpp
00001:
00002: /*
00003: -------------------------------------------------------------------------
00004: This file is part of WxWidgetsExtensions library.
00005: -------------------------------------------------------------------------
00006:
00007: WxExtLib (WxWidgetsExtensions) library
00008: -----------------------------
00009:
00010: COPYRIGHT NOTICE:
00011:
00012: WxExtLib library Copyright (c) 2003-2007 Daniel Käps
00013:
00014: The WxWidgetsExtensions library and associated documentation files (the
00015: "Software") is provided "AS IS". The author(s) disclaim all
00016: warranties, expressed or implied, including, without limitation, the
00017: warranties of merchantability and of fitness for any purpose. The
00018: author(s) assume no liability for direct, indirect, incidental,
00019: special, exemplary, or consequential damages, which may result from
00020: the use of or other dealings in the Software, even if advised of the
00021: possibility of such damage.
00022:
00023: Permission is hereby granted, free of charge, to any person obtaining
00024: a copy of this Software, to deal in the Software without restriction,
00025: including without limitation the rights to use, copy, modify, merge,
00026: publish, distribute, sublicense, and/or sell copies of the Software,
00027: and to permit persons to whom the Software is furnished to do so,
00028: subject to the following conditions:
00029:
00030: 1. The origin of this source code must not be misrepresented.
00031: 2. Altered versions must be plainly marked as such and must not be
00032: misrepresented as being the original source.
00033: 3. This Copyright notice may not be removed or altered from any
00034: source or altered source distribution.
00035:
00036: End of WxExtLib library Copyright Notice
00037:
00038: -------------------------------------------------------------------------
00039: */
00040:
00041: #ifndef _NO_HEADER_INCLUDE
00042:
00043: #if defined(__GNUG__) && (!defined(__APPLE__)) && (!(defined M_NoPragmaInterface))
00044: #pragma implementation "WxMisc.cpp"
00045: #endif
00046:
00047: #include "WxExtLibConfig.h"
00048:
00049: // For compilers that support precompilation, includes "wx/wx.h".
00050: #include "wx/wxprec.h"
00051:
00052: #ifdef __BORLANDC__
00053: #pragma hdrstop
00054: #endif
00055:
00056: #include "WxMisc.h"
00057:
00058: #include <wx/mstream.h>
00059:
00060: #if wxUSE_GUI
00061: # include <wx/dc.h>
00062: # include <wx/dcclient.h>
00063:
00064: # ifdef M_WxExtLib_IsFilteredDIBEnabled
00065: # include "magick/studio.h"
00066: # include "magick/error.h"
00067: # include "magick/image.h"
00068: # include "magick/enhance.h"
00069: # include "magick/constitute.h"
00070: # include "ImageMagickExtensions.h"
00071: # endif
00072: #endif // wxUSE_GUI
00073:
00074: #include "safecast.h"
00075:
00076: #if (M_WxExtLib_IsUseGraphicsHelper == 1)
00077: # include <GraphicsMisc.h>
00078: #endif
00079:
00080: #endif // _NO_HEADER_INCLUDE
00081:
00082: //=========================================================================
00083:
00084: wxMinimalTimeInterval::wxMinimalTimeInterval ()
00085: {
00086: m_IsInitialized = false;
00087: }
00088:
00089: void wxMinimalTimeInterval::setMinimalTimeInterval (long MinimalTimeIntervalMS)
00090: {
00091: m_MinimalTimeIntervalMS = MinimalTimeIntervalMS;
00092: }
00093:
00094: void wxMinimalTimeInterval::setBegin ()
00095: {
00096: #ifdef M_MinimalTimeInterval_UseGetTickCount
00097: m_BeginUpTimeMS = ::GetTickCount();
00098: #else
00099: // m_StopWatch.Start ();
00100: m_BeginTimeMSLongLong = wxGetLocalTimeMillis();
00101: #endif
00102: m_IsInitialized = true;
00103: }
00104:
00105: bool wxMinimalTimeInterval::check ()
00106: {
00107: // return true if start of interval is unspecified, i.e. no start event
00108: // has taken place
00109: if (!m_IsInitialized)
00110: return true;
00111:
00112: #ifdef M_MinimalTimeInterval_UseGetTickCount
00113: DWORD CurrentUpTimeMS = ::GetTickCount ();
00114: DWORD ElapsedTimeMS;
00115: if (m_BeginUpTimeMS > CurrentUpTimeMS)
00116: {
00117: // handle timer overflow?
00118: // CurrentUpTimeMS += 0xFFFFFFFF - CurrentUpTimeMS;
00119: // m_BeginUpTimeMS = 0;
00120: ElapsedTimeMS = CurrentUpTimeMS - m_BeginUpTimeMS;
00121: }
00122: else
00123: {
00124: ElapsedTimeMS = CurrentUpTimeMS - m_BeginUpTimeMS;
00125: }
00126:
00127: // if (ElapsedTimeMS >= m_MinimalTimeIntervalMS)
00128: if (cast_is_equal_smaller (m_MinimalTimeIntervalMS, ElapsedTimeMS))
00129: {
00130: return true;
00131: }
00132: else
00133: {
00134: return false;
00135: }
00136: #else
00137: // BUG doesn't handle timer overflows (will happen after
00138: // about 48 days)
00139: // return (m_StopWatch.Time () > m_MinimalTimeIntervalMS);
00140:
00141: // alternative implementation: use wxGetLocalTimeMillis() which
00142: // uses wxLongLong and thus has no overflow for about eternal years
00143: wxLongLong CurrentTimeMSLongLong = wxGetLocalTimeMillis();
00144: wxLongLong MinimalTimeIntervalMSLongLong = m_MinimalTimeIntervalMS;
00145: wxLongLong ElapsedTimeMSLongLong = CurrentTimeMSLongLong - m_BeginTimeMSLongLong;
00146:
00147: // WARN don't know if ElapsedTimeMS<0 may happen - under e.g. Win9x this seems to be
00148: // the case after adjusting the system clock backwards; however, adjusting
00149: // the system clock forwards will yield incorrect results too -
00150: // TODO check if adjusting system time influences running processes under
00151: // Linux, Unix
00152: // WARN workaround for ElapsedTimeMS < 0
00153: if (ElapsedTimeMSLongLong < 0)
00154: {
00155: setBegin();
00156: return false;
00157: }
00158: if (ElapsedTimeMSLongLong >= MinimalTimeIntervalMSLongLong)
00159: {
00160: return true;
00161: }
00162: else
00163: {
00164: return false;
00165: }
00166: #endif
00167: }
00168:
00169: //=========================================================================
00170:
00171: bool convertStringToLong (const char * CharPtr, long & Long)
00172: {
00173: // replacement for:
00174: // if (sscanf (CharPtr,"%d%c", & TempLong, &DummyChar) !=1 ) { // handle error }
00175:
00176: bool IsOk = false;
00177: char * EndCharPtr = NULL;
00178: int Base = 10;
00179: long TempLong = strtol (CharPtr, & EndCharPtr, Base);
00180:
00181: if (EndCharPtr != NULL
00182: && EndCharPtr != CharPtr
00183: && *EndCharPtr == '\0')
00184: {
00185: // WARN should use macros for minimal/maximal long values
00186: // defined in some header file somewhere
00187: // using macros LONG_MAX and LONG_MIN may require #include <limits.h>
00188: if ((TempLong != LONG_MAX)
00189: && (TempLong != LONG_MIN))
00190: {
00191: IsOk = true;
00192: Long = TempLong;
00193: }
00194: }
00195: return IsOk;
00196: }
00197:
00198: // same as above, but for 'unsigned long' instead of 'long'
00199: bool convertStringToLong (const char * CharPtr, unsigned long & Long)
00200: {
00201: // replacement for:
00202: // if (sscanf (CharPtr,"%u%c", & TempLong, &DummyChar) !=1 ) { // handle error }
00203:
00204: bool IsOk = false;
00205: char * EndCharPtr = NULL;
00206: int Base = 10;
00207: unsigned long TempLong = strtoul (CharPtr, & EndCharPtr, Base);
00208:
00209: if (EndCharPtr != NULL
00210: && EndCharPtr != CharPtr
00211: && *EndCharPtr == '\0')
00212: {
00213: // using macros ULONG_MAX may require #include <limits.h>
00214: if ((TempLong != ULONG_MAX)
00215: && (TempLong != 0))
00216: {
00217: IsOk = true;
00218: Long = TempLong;
00219: }
00220: }
00221: return IsOk;
00222: }
00223:
00224: //=========================================================================
00225:
00226: void convertAsciiToHtml (const char * AsciiStringCharPtr, wxString & HtmlString,
00227: bool IsTranslateNewlines,
00228: long WxAsciiToHtmlFlags)
00229: {
00230: int HtmlStringLength = 0;
00231: HtmlString.Clear();
00232:
00233: # define M_HandleReplace(HtmlCharSequence) \
00234: \
00235: if (StageIndex == 0) \
00236: { \
00237: /* PERFORMANCE calling strlen() should be replaced by some */ \
00238: /* static string length table */ \
00239: HtmlStringLength += strlen(HtmlCharSequence); \
00240: } \
00241: else \
00242: { \
00243: HtmlString += HtmlCharSequence; \
00244: }
00245:
00246: # define M_HandleNonReplace \
00247: \
00248: if (StageIndex == 0) \
00249: { \
00250: HtmlStringLength += 1; \
00251: } \
00252: else \
00253: { \
00254: HtmlString += (char) CharAsInt; \
00255: }
00256:
00257: // now the loop in two stages:
00258: // - first stage:
00259: // determine length of resulting HTML string and pre-alloc to
00260: // this length to avoid multiple reallocations
00261: // - second stage:
00262: // do actual replacement/append
00263: for (int StageIndex = 0; StageIndex < 2; ++StageIndex)
00264: {
00265: bool IsLeadingSpace = true;
00266:
00267: if (StageIndex == 1)
00268: {
00269: HtmlString.Alloc (HtmlStringLength);
00270: }
00271:
00272: const char * CurrentAsciiStringCharPtr = NULL;
00273:
00274: // loop over all characters in input string
00275: for (CurrentAsciiStringCharPtr = AsciiStringCharPtr;
00276: *CurrentAsciiStringCharPtr!='\0'; ++CurrentAsciiStringCharPtr)
00277: {
00278: char Char = *CurrentAsciiStringCharPtr;
00279: int CharAsInt = Char;
00280:
00281: bool IsSpaceChar = false;
00282:
00283: switch (CharAsInt)
00284: {
00285: case '<':
00286: M_HandleReplace ("<");
00287: break;
00288: case '>':
00289: M_HandleReplace (">");
00290: break;
00291: case '&':
00292: M_HandleReplace ("&");
00293: break;
00294: case '"':
00295: M_HandleReplace (""");
00296: break;
00297: case ' ':
00298: case '\t':
00299: IsSpaceChar = true;
00300: if ((IsLeadingSpace && ((WxAsciiToHtmlFlags & wxAsciiToHtml_ConvertLeadingSpaces) != 0))
00301: || ((WxAsciiToHtmlFlags & wxAsciiToHtml_ConvertAllSpaces) != 0))
00302: {
00303: if (Char == '\t')
00304: {
00305: M_HandleReplace (" ");
00306: }
00307: else
00308: {
00309: M_HandleReplace (" ");
00310: }
00311: }
00312: else
00313: {
00314: M_HandleNonReplace;
00315: }
00316: break;
00317: case '\r':
00318: if (IsTranslateNewlines)
00319: {
00320: // it is assumed that next character it '\n' and this
00321: // will cause "<br>\r\n" to be appended
00322: M_HandleReplace ("");
00323: }
00324: else
00325: {
00326: M_HandleNonReplace;
00327: }
00328: break;
00329: case '\n':
00330: if (IsTranslateNewlines)
00331: {
00332: M_HandleReplace ("<br>\r\n");
00333:
00334: IsSpaceChar = true;
00335: IsLeadingSpace = true;
00336: }
00337: else
00338: {
00339: M_HandleNonReplace;
00340: }
00341: default:
00342: M_HandleNonReplace;
00343: break;
00344: }
00345:
00346: if (IsLeadingSpace && (!IsSpaceChar))
00347: {
00348: IsLeadingSpace = false;
00349: }
00350: }
00351: }
00352:
00353: #undef M_HandleReplace
00354: #undef M_HandleNonReplace
00355:
00356: }
00357:
00358: wxString convertAsciiToHtml (const char * AsciiStringCharPtr,
00359: bool IsTranslateNewlines,
00360: long WxAsciiToHtmlFlags)
00361: {
00362: wxString HtmlString;
00363: convertAsciiToHtml (AsciiStringCharPtr, HtmlString,
00364: IsTranslateNewlines,
00365: WxAsciiToHtmlFlags);
00366:
00367: return HtmlString;
00368: }
00369:
00370: //-------------------------------------------------------------------------
00371:
00372: wxString formatColourToHtmlParam (const wxColour & Colour)
00373: {
00374: return wxString::Format ("#%02x%02x%02x",
00375: Colour.Red(), Colour.Green(), Colour.Blue());
00376: }
00377:
00378: //=========================================================================
00379:
00380: bool getHtmlTagParamAsDouble (const wxHtmlTag & HtmlTag,
00381: const wxString & ParamNameString, double * Double)
00382: {
00383: wxString ParamValueString = HtmlTag.GetParam (ParamNameString);
00384: return parseDoubleFromAnyLocaleString (ParamValueString, Double);
00385: }
00386:
00387: bool parseDoubleFromAnyLocaleString (const wxString & InputValueString, double * Double)
00388: {
00389: // HACK to get around problem with locale for float/double formatting
00390: // wxString::Format() and HtmlTag::ScanParam() seem to use current locale
00391: // settings, but sometimes we want to parse (as strings) hard-coded double
00392: // parameters (e.g. occuring in HTML templates)
00393: // Normally ScanParam() would fail (depending on the locale setting).
00394:
00395: // BUG
00396: // 1) the used approach probably fails if the input strings contains
00397: // thousands-separators (grouping characters)
00398: // 2) the used approach probably fails if a comma is used to separate
00399: // a sequence of numbers (possibly written without spaces)
00400:
00401: // WARN
00402: // - don't know if there are other decimal separator charcaters than
00403: // comma and point. If so, parsing for them would have to be added too.
00404:
00405: wxString ValueString (InputValueString);
00406:
00407: // try to parse in two different ways: once with occurences of
00408: // points replaced by commas and once with occurences of commas
00409: // replaced by points
00410: int WithCommaParsedCharacterCount = 0;
00411: double WithCommaParsedDouble = 0.;
00412: ValueString.Replace (".", ",", true);
00413: int WithCommaParsedArgumentCount = wxSscanf (ValueString.c_str(), "%lf%n",
00414: & WithCommaParsedDouble,
00415: & WithCommaParsedCharacterCount);
00416:
00417: int WithPointParsedCharacterCount = 0;
00418: double WithPointParsedDouble = 0.;
00419: ValueString.Replace (",", ".", true);
00420: int WithPointParsedArgumentCount = wxSscanf (ValueString.c_str(), "%lf%n",
00421: & WithPointParsedDouble,
00422: & WithPointParsedCharacterCount);
00423:
00424: // determine which of both possible results to use: if both ways we could
00425: // parse at least on parameter, we use the result where more characters were
00426: // parsed (quite hacky, admittedly). It would be better to ask for
00427: // the setting of the locale, but i don't know which function is available
00428: // (if any) for this.
00429: bool IsUsePointParsedDouble = true;
00430: if (WithPointParsedArgumentCount > 0
00431: && WithPointParsedArgumentCount == 0)
00432: {
00433: IsUsePointParsedDouble = true;
00434: }
00435: else if (WithPointParsedArgumentCount == 0
00436: && WithCommaParsedArgumentCount > 0)
00437: {
00438: IsUsePointParsedDouble = false;
00439: }
00440: else if (WithPointParsedArgumentCount > 0
00441: && WithCommaParsedArgumentCount > 0)
00442: {
00443: IsUsePointParsedDouble = (WithPointParsedCharacterCount >= WithCommaParsedCharacterCount);
00444: }
00445:
00446: // set function's output values
00447: int ParsedArgumentCount = IsUsePointParsedDouble
00448: ? WithPointParsedArgumentCount : WithCommaParsedArgumentCount;
00449: if (IsUsePointParsedDouble)
00450: {
00451: * Double = WithPointParsedDouble;
00452: }
00453: else
00454: {
00455: * Double = WithCommaParsedDouble;
00456: }
00457:
00458: return ParsedArgumentCount > 0;
00459: }
00460:
00461: //=========================================================================
00462:
00463: wxNumberFormatOptions::wxNumberFormatOptions ()
00464: {
00465: m_GroupSize = 3;
00466: m_GroupSeparatorChar = ',';
00467: m_DecimalSeparatorChar = '.';
00468: }
00469:
00470: wxNumberFormatOptions::wxNumberFormatOptions (int GroupSize, char GroupSeparatorChar,
00471: char DecimalSeparatorChar)
00472: {
00473: set (GroupSize, GroupSeparatorChar, DecimalSeparatorChar);
00474: }
00475:
00476: void wxNumberFormatOptions::set (int GroupSize, char GroupSeparatorChar,
00477: char DecimalSeparatorChar)
00478: {
00479: m_GroupSize = GroupSize;
00480: m_GroupSeparatorChar = GroupSeparatorChar;
00481: m_DecimalSeparatorChar = DecimalSeparatorChar;
00482: }
00483:
00484: //-------------------------------------------------------------------------
00485:
00486: wxNumberFormattingInternals::wxNumberFormattingInternals()
00487: {
00488: m_IsOkay = false;
00489: }
00490:
00491: //-------------------------------------------------------------------------
00492:
00493: void detectNumberFormattingInternals(wxNumberFormattingInternals * NumberFormattingInternals)
00494: {
00495: wxString TempString;
00496:
00497: bool IsOkay = false;
00498:
00499: for_once
00500: {
00501: // determine decimal separator string
00502: double SampleDouble = 1.4;
00503:
00504: TempString = wxString::Format ("%f", SampleDouble);
00505: const char * TempCharPtr = TempString.c_str();
00506:
00507: if (TempCharPtr[1] == ',')
00508: NumberFormattingInternals -> m_DecimalSeparatorChar = ',';
00509: else if (TempCharPtr[1] == '.')
00510: NumberFormattingInternals -> m_DecimalSeparatorChar = '.';
00511: else
00512: break;
00513:
00514: if ((TempCharPtr[0] != '1') || (TempCharPtr[2] != '4'))
00515: break;
00516:
00517: IsOkay = true;
00518: }
00519:
00520: NumberFormattingInternals -> m_IsOkay = IsOkay;
00521: }
00522:
00523: //-------------------------------------------------------------------------
00524:
00525: void formatLong (const wxString & FormatString,
00526: wxNumberFormatOptions & NumberFormatOptions,
00527: long Long,
00528: wxString & String,
00529: wxNumberFormattingInternals * NumberFormattingInternals)
00530: {
00531: // example: -123456.789 -> -123,456.789
00532:
00533: if (NumberFormattingInternals == NULL)
00534: {
00535: wxNumberFormattingInternals TempNumberFormattingInternals;
00536: detectNumberFormattingInternals (& TempNumberFormattingInternals);
00537: NumberFormattingInternals = & TempNumberFormattingInternals;
00538: }
00539:
00540: if (!NumberFormattingInternals -> m_IsOkay)
00541: {
00542: String = wxString::Format (FormatString, Long);
00543: return;
00544: }
00545:
00546: // format into temporary string and add grouping if desired
00547: wxString TempString;
00548: TempString = wxString::Format (FormatString, Long);
00549:
00550: formatNumberStringWithGrouping (TempString,
00551: NumberFormatOptions,
00552: String,
00553: NumberFormattingInternals);
00554: }
00555:
00556: void formatDouble (const wxString & FormatString,
00557: wxNumberFormatOptions & NumberFormatOptions,
00558: double Double,
00559: wxString & String,
00560: wxNumberFormattingInternals * NumberFormattingInternals)
00561: {
00562: // example: -123456.789 -> -123,456.789
00563:
00564: wxNumberFormattingInternals TempNumberFormattingInternals;
00565: if (NumberFormattingInternals == NULL)
00566: {
00567: detectNumberFormattingInternals (& TempNumberFormattingInternals);
00568: NumberFormattingInternals = & TempNumberFormattingInternals;
00569: }
00570:
00571: if (!NumberFormattingInternals -> m_IsOkay)
00572: {
00573: String = wxString::Format (FormatString, Double);
00574: return;
00575: }
00576:
00577: // format into temporary string and add grouping if desired
00578: wxString TempString;
00579: TempString = wxString::Format (FormatString, Double);
00580:
00581: formatNumberStringWithGrouping (TempString,
00582: NumberFormatOptions,
00583: String,
00584: NumberFormattingInternals);
00585: }
00586:
00587: //-------------------------------------------------------------------------
00588:
00589: void formatNumberStringWithGrouping (const wxString & NumberString,
00590: wxNumberFormatOptions & NumberFormatOptions,
00591: wxString & String,
00592: wxNumberFormattingInternals * NumberFormattingInternals)
00593: {
00594: /* from manual page of fprintf():
00595: For some numeric conversions a radix character (`decimal point') or thousands' grouping character is used. The
00596: actual character used depends on the LC_NUMERIC part of the locale. The POSIX locale uses `.' as radix charac-
00597: ter, and does not have a grouping character. Thus,
00598: printf("%'.2f", 1234567.89);
00599: results in `1234567.89' in the POSIX locale, in `1234567,89' in the nl_NL locale, and in `1.234.567,89' in the
00600: da_DK locale.
00601:
00602: thus:
00603: - newer version of the standard library may have support for using thousand grouping
00604: characters, on an optional basis
00605: - the user cannot force use of grouping if his/her locale is not configured for it
00606: - scanf functions may not understand the grouping character format string flag
00607: */
00608:
00609: // parse formatted temporary string and determine certain positions, such
00610: // as non-fractional digits
00611: const char * CharPtr = NumberString.c_str();
00612: int Index = 0;
00613: int DecimalSeparatorIndex = -1;
00614: int DigitStartIndex = -1;
00615: int DigitEndIndex = -1;
00616: while (*CharPtr != '\0')
00617: {
00618: char Char = *CharPtr;
00619: if (Char == NumberFormattingInternals -> m_DecimalSeparatorChar)
00620: {
00621: if (DecimalSeparatorIndex == -1)
00622: DecimalSeparatorIndex = Index;
00623: }
00624:
00625: if (wxIsdigit (Char))
00626: {
00627: if (DigitStartIndex == -1)
00628: {
00629: DigitStartIndex = Index;
00630: }
00631: if ((*(CharPtr + 1) == '\0')
00632: && DigitEndIndex == -1)
00633: {
00634: DigitEndIndex = Index + 1;
00635: }
00636: }
00637: else
00638: {
00639: if (DigitStartIndex != -1
00640: && DigitEndIndex == -1)
00641: {
00642: DigitEndIndex = Index;
00643: }
00644: }
00645:
00646: ++Index;
00647: ++CharPtr;
00648: }
00649:
00650: bool IsUseGrouping = NumberFormatOptions.m_GroupSize > 0;
00651: int GroupCharacterCount = 0;
00652:
00653: if (IsUseGrouping
00654: && (DigitStartIndex != -1)
00655: && (DigitEndIndex != -1))
00656: {
00657: GroupCharacterCount = ((DigitEndIndex - DigitStartIndex) / NumberFormatOptions.m_GroupSize);
00658: if (GroupCharacterCount > 0)
00659: --GroupCharacterCount;
00660: }
00661:
00662: String.Clear();
00663: String.Alloc (NumberString.Length() + GroupCharacterCount);
00664:
00665: // now produce string with inserted grouping characters
00666: CharPtr = NumberString.c_str();
00667: Index = 0;
00668: while (*CharPtr != '\0')
00669: {
00670: if (IsUseGrouping
00671: && (DigitStartIndex != -1)
00672: && (DigitEndIndex != -1)
00673: && (Index >= DigitStartIndex)
00674: && (Index < DigitEndIndex))
00675: {
00676: if ((Index < DigitEndIndex)
00677: && (Index > DigitStartIndex)
00678: && (((DigitEndIndex - Index) % NumberFormatOptions.m_GroupSize) == 0))
00679: {
00680: // insert grouping character
00681: String += NumberFormatOptions.m_GroupSeparatorChar;
00682: }
00683: }
00684: if (Index == DecimalSeparatorIndex)
00685: {
00686: // replace decimal separator
00687: String += NumberFormatOptions.m_DecimalSeparatorChar;
00688: }
00689: else
00690: {
00691: // otherwise add characters from temporary string
00692: String += *CharPtr;
00693: }
00694:
00695: ++Index;
00696: ++CharPtr;
00697: }
00698: }
00699:
00700: //-------------------------------------------------------------------------
00701:
00702: #define M_CheckString(DesiredResult) \
00703: if (String != DesiredResult) \
00704: { \
00705: wxString MessageString; \
00706: MessageString << "string \"" << String << "\" obtained instead of desired result \"" << DesiredResult << "\""; \
00707: wxASSERT_MSG (false, MessageString); \
00708: IsError = true; \
00709: break; \
00710: } \
00711:
00712: bool testNumberFormat()
00713: {
00714: wxString String;
00715: wxNumberFormatOptions NumberFormatOptions (2, '.', ';');
00716:
00717: bool IsOkay = false;
00718: bool IsError = false;
00719: for_once
00720: {
00721: // NOTE: different compilers/libraries may use differing
00722: // interpretation of printf() format specifiers, causing M_CheckString
00723: // to indicate failure
00724:
00725: NumberFormatOptions.set (2, '.', ';');
00726: formatDouble ("%.1f", NumberFormatOptions, 12345678.9, String);
00727: M_CheckString ("12.34.56.78;9");
00728:
00729: NumberFormatOptions.set (2, '.', ';');
00730: formatDouble ("%g", NumberFormatOptions, 9, String);
00731: M_CheckString ("9");
00732:
00733: NumberFormatOptions.set (2, '.', ';');
00734: formatDouble ("%g", NumberFormatOptions, 9e50, String);
00735: #if (defined(_MSC_VER)) // ?? || (defined(__BORLANDC__))
00736: M_CheckString ("9e+050");
00737: #else
00738: M_CheckString ("9e+50");
00739: #endif
00740:
00741: NumberFormatOptions.set (4, '.', ';');
00742: formatDouble ("%g", NumberFormatOptions, 23456789, String);
00743: #if (defined(_MSC_VER)) // ?? || (defined(__BORLANDC__))
00744: M_CheckString ("2;34568e+007");
00745: #else
00746: M_CheckString ("2;34568e+07");
00747: #endif
00748:
00749: NumberFormatOptions.set (1, ' ', ';');
00750: formatDouble ("%.0f", NumberFormatOptions, -3456789, String);
00751: M_CheckString ("-3 4 5 6 7 8 9");
00752:
00753: NumberFormatOptions.set (4, '.', ';');
00754: formatDouble ("%g", NumberFormatOptions, 56789, String);
00755: M_CheckString ("5.6789");
00756:
00757: NumberFormatOptions.set (4, '.', ';');
00758: formatDouble ("%g", NumberFormatOptions, 6789, String);
00759: M_CheckString ("6789");
00760:
00761: // still, specified field width is modified because of inserting
00762: // grouping characters
00763: NumberFormatOptions.set (3, '.', ',');
00764: formatLong ("%14ld", NumberFormatOptions, -1123456789, String);
00765: M_CheckString (" -1.123.456.789");
00766:
00767: NumberFormatOptions.set (3, '.', ',');
00768: formatLong ("%ld", NumberFormatOptions, 0, String);
00769: M_CheckString ("0");
00770:
00771: IsOkay = true;
00772: }
00773:
00774: return IsOkay;
00775: }
00776:
00777: #undef M_CheckString
00778:
00779: //=========================================================================
00780:
00781: wxDateTime::Month getMonthFromMonthIndex (int MonthIndex) // MonthIndex starting from 1, _not_ 0!
00782: {
00783: switch (MonthIndex)
00784: {
00785: case 1: return wxDateTime::Jan;
00786: case 2: return wxDateTime::Feb;
00787: case 3: return wxDateTime::Mar;
00788: case 4: return wxDateTime::Apr;
00789: case 5: return wxDateTime::May;
00790: case 6: return wxDateTime::Jun;
00791: case 7: return wxDateTime::Jul;
00792: case 8: return wxDateTime::Aug;
00793: case 9: return wxDateTime::Sep;
00794: case 10: return wxDateTime::Oct;
00795: case 11: return wxDateTime::Nov;
00796: case 12: return wxDateTime::Dec;
00797: }
00798: return wxDateTime::Inv_Month;
00799: }
00800:
00801: int getMonthIndexFromMonth (wxDateTime::Month Month) // MonthIndex starting from 1, _not_ 0!
00802: {
00803: switch (Month)
00804: {
00805: case wxDateTime::Jan: return 1;
00806: case wxDateTime::Feb: return 2;
00807: case wxDateTime::Mar: return 3;
00808: case wxDateTime::Apr: return 4;
00809: case wxDateTime::May: return 5;
00810: case wxDateTime::Jun: return 6;
00811: case wxDateTime::Jul: return 7;
00812: case wxDateTime::Aug: return 8;
00813: case wxDateTime::Sep: return 9;
00814: case wxDateTime::Oct: return 10;
00815: case wxDateTime::Nov: return 11;
00816: case wxDateTime::Dec: return 12;
00817: default:
00818: break;
00819: }
00820: return 0;
00821: }
00822:
00823: //=========================================================================
00824:
00825: void getDecomposedDateFormatString (const wxString & InputFormatString,
00826: wxString & DecomposedDateFormatString)
00827: {
00828: // our sample date: Monday, 22 October 1990
00829: // - the numbers should be unique (don't use 12 December or the like)
00830: // - the numbers should be 2-digit (so we don't have to care if a leading
00831: // zero is printed or is not printed) - to simplify things a little
00832: wxDateTime SampleDateTime (/* day */ 22,
00833: /* month */ wxDateTime::Oct,
00834: /* year */ 1990);
00835: // wxDateTime_t hour = 0, wxDateTime_t minute = 0,
00836: // wxDateTime_t second = 0, wxDateTime_t millisec = 0)
00837:
00838: // WARN
00839: // - maybe it would be more appropriate to call CallStrftime() directly
00840: // instead of calling wxDateTime::Format()
00841: // - should check if wxDateTime::Format()/CallStrftime() returned
00842: // an error
00843:
00844: // get abbreviated and full weekday string for Monday for current locale
00845: wxString AbbreviatedSampleWeekdayString = SampleDateTime.Format ("%a");
00846: wxString FullSampleWeekdayString = SampleDateTime.Format ("%A");
00847:
00848: // get abbreviated and full month name for October for current locale
00849: wxString AbbreviatedSampleMonthString = SampleDateTime.Format ("%b");
00850: wxString FullSampleMonthString = SampleDateTime.Format ("%B");
00851:
00852: // format the sample date
00853: wxString SampleDateTimeString = SampleDateTime.Format (InputFormatString);
00854:
00855: // replace occurences of "%" with "%%" first:
00856: SampleDateTimeString.Replace ("%", "%%");
00857:
00858: // BUG: simply searching/replacing "%X" is incorrect if the format
00859: // string contains the sequence "%%" (then, the "%a" in "%%a" is not
00860: // a placeholder) - to fix, add full parsing of format string
00861: //
00862: SampleDateTimeString.Replace (FullSampleWeekdayString, "%A");
00863: SampleDateTimeString.Replace (AbbreviatedSampleWeekdayString, "%a");
00864: SampleDateTimeString.Replace ("22", "%d");
00865: SampleDateTimeString.Replace (FullSampleMonthString, "%B");
00866: SampleDateTimeString.Replace (AbbreviatedSampleMonthString, "%b");
00867: SampleDateTimeString.Replace ("10", "%m");
00868: SampleDateTimeString.Replace ("1990", "%Y");
00869: SampleDateTimeString.Replace ("90", "%y"); // maybe use %Y here too
00870:
00871: // now, SampleDateTimeString should contain a valid format string according
00872: // to the current locale setting
00873: DecomposedDateFormatString = SampleDateTimeString;
00874:
00875: // TODO: add checking if it was actually possible to determine
00876: // the decomposed format string; add a fall-back
00877: }
00878:
00879: void getDecomposedDateFormatStringX (wxString & DecomposedDateFormatString,
00880: bool IsLongFormat)
00881: {
00882: if (IsLongFormat)
00883: {
00884: #if defined(__WXMSW__)
00885: #if (!defined(_MSC_VER)) && (!defined(__BORLANDC__))
00886: # pragma message ("Please check if your compiler/OS uses '%%#x' or '%%Ex' for alternative date format")
00887: #endif
00888: // the format string to indicate alternative date/time
00889: // representation differs in MSW/VC++, Borland C++
00890: // TODO check which other compilers use %#c instead of %Ec
00891: getDecomposedDateFormatString ("%#x", DecomposedDateFormatString);
00892: #else
00893: getDecomposedDateFormatString ("%Ex", DecomposedDateFormatString);
00894: #endif
00895: }
00896: else
00897: {
00898: getDecomposedDateFormatString ("%x", DecomposedDateFormatString);
00899: }
00900: }
00901:
00902: bool removeWeekdayFromDateFormatString (const wxString & DateFormatString,
00903: wxString & WithoutWeekdayDateFormatString)
00904: {
00905: // make format string with weekday placeholder removed:
00906: // remove %a or %A, remove following spaces, punctuation characters etc.
00907: // WARN may have to remove spaces, punctuation characters before %a, %A as well
00908: //
00909: // BUG: simply searching for "%X" is incorrect if the format string
00910: // contains the sequence "%%" (then, the "%a" in "%%a" is not
00911: // a placeholder) - to fix, add full parsing of format string
00912: //
00913: int WeekdayPlaceholderCharIndex = DateFormatString.Find ("%a");
00914: if (WeekdayPlaceholderCharIndex == wxNOT_FOUND)
00915: WeekdayPlaceholderCharIndex = DateFormatString.Find ("%A");
00916: if (WeekdayPlaceholderCharIndex != wxNOT_FOUND)
00917: {
00918: int CurrentCharIndex = WeekdayPlaceholderCharIndex + 2 /* strlen ("%a") */;
00919: for (; cast_is_smaller (CurrentCharIndex, DateFormatString.Length());
00920: ++CurrentCharIndex)
00921: {
00922: int CurrentChar = DateFormatString [CurrentCharIndex];
00923: if (!(wxIsspace (CurrentChar)
00924: || (wxIspunct (CurrentChar) && CurrentChar != '%')))
00925: break;
00926: }
00927: WithoutWeekdayDateFormatString = DateFormatString;
00928: WithoutWeekdayDateFormatString.Remove (WeekdayPlaceholderCharIndex,
00929: CurrentCharIndex-WeekdayPlaceholderCharIndex);
00930:
00931: return true;
00932: }
00933: return false;
00934: }
00935:
00936: //-------------------------------------------------------------------------
00937:
00938: void formatDate (const wxDateTime & DateTime, wxString & String,
00939: bool IsLongFormat)
00940: {
00941: // NOTE date formatting using "%#x" or "%Ex"
00942: // sometimes wxDateTime uses its own implementation which
00943: // doesn't understand 'E' or '#'. The wxWindows implementation
00944: // is apparently used for dates before 2 Janary 1970
00945: // (an assertion failure is reported, and the output string
00946: // is set to the format string minus the percent character)
00947: //
00948: // following hack is not required anymore, now there
00949: // is getDecomposedDateFormatString() which works better
00950: //
00951: // if (TextCtrlContentString.IsSameAs ("#x")
00952: // || TextCtrlContentString.IsSameAs ("Ex"))
00953: // {
00954: // // since we don't know if the current locale has
00955: // // DAY MONTH or MONTH DAY order, we output the date with the
00956: // // month name to avoid any ambiguities
00957: // TextCtrlContentString = TempDateTime.Format("%d %B %Y");
00958: // }
00959:
00960: wxString DateFormatString;
00961: getDecomposedDateFormatStringX (DateFormatString, IsLongFormat);
00962:
00963: String = DateTime.Format (DateFormatString);
00964: }
00965:
00966: //-------------------------------------------------------------------------
00967:
00968: // parseDate()
00969: // BUG
00970: // - correct parsing of input (in case of occurences of "%%") would
00971: // be required instead of simply replacing %X, if any of the format
00972: // strings tried contains "%%"
00973: //
00974: bool parseDate (const wxString & String, wxDateTime & DateTime)
00975: {
00976: // wxDateTime::ParseDate() works quite well unless the year in the string
00977: // is 2 digit and less than 31... Such a date string is generated
00978: // by Format("%#x") if no locale or some English locale was set
00979: // (so the output is e.g. 02/19/04)
00980: // ParseDate() doesn't handle such a date.
00981: //
00982: // ParseFormat() may only be able to parse formats like dd/mm/yy or
00983: // mm/dd/yy, because possibly 'strptime' is not available.
00984: // In this case, ParseFormat() cannot parse a date like '2 March 2002'.
00985: //
00986: // the following hack was used: The solution is to use try first
00987: // ParseFormat() and if it fails try ParseDate().
00988: // However, this still doesn't work well because of the following problem:
00989: //
00990: // possibly BUG in wxDateTime::ParseFormat():
00991: // for "%x", it uses "%d/%m/%y" as format if the time zone is e.g. European.
00992: // But the locale setting may well differ from the time zone setting.
00993: // (scope: wxWindows 2.4.1).
00994: // Same problem may exist for ParseDate().
00995: //
00996: //!! A solution to this problem would be to make a dummy print of
00997: //!! a fixed date like 10 November 2012 (2012-11-10) and then
00998: //!! look in the output string if it was printed in day-month
00999: //!! or month-day order
01000: //!! we could even try to construct a format string from the dummy
01001: //!! result
01002: // (the last idea is now implemented with getDecomposedDateFormatString())
01003: //
01004: // hack is obsolete now since we have getDecomposedDateFormatString()
01005: // which works well
01006: // --->
01007: // WARN see bug in ParseFormat() above
01008: // const char * EndCharPtr = TempDateTime.ParseFormat (BeginCharPtr, "%x");
01009: // bool IsOk = true;
01010: // if ((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0))
01011: // {
01012: // // try conversion with ParseDate() if ParseFormat() failed
01013: // EndCharPtr = TempDateTime.ParseDate (BeginCharPtr);
01014: // if ((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0))
01015: // {
01016: // IsOk = false;
01017: // }
01018: // }
01019: // <----
01020:
01021: const char * BeginCharPtr = String.c_str();
01022: const char * EndCharPtr = NULL;
01023:
01024: // try parsing the input as short date format:
01025: wxString ShortDateFormatString;
01026: getDecomposedDateFormatStringX (ShortDateFormatString, false);
01027: // note: under some platforms/locals, %x is equal to "%d.%m.%Y,
01028: // but we must parse with 2-digit year first because a 2-digit year
01029: // in the input may be interpreted as first-century year by
01030: // wxDateTime::ParseFormat().
01031: ShortDateFormatString.Replace ("%Y", "%y"); // make year 2-digit
01032: EndCharPtr = DateTime.ParseFormat (BeginCharPtr, ShortDateFormatString);
01033: if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01034: {
01035: return true;
01036: }
01037:
01038: // try to parse input as short format, but with 4-digit year now
01039: ShortDateFormatString.Replace ("%y", "%Y");
01040: {
01041: EndCharPtr = DateTime.ParseFormat (BeginCharPtr, ShortDateFormatString);
01042: if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01043: {
01044: return true;
01045: }
01046: }
01047:
01048: // try to parse input as long date format
01049: wxString DateFormatString;
01050: getDecomposedDateFormatStringX (DateFormatString, true);
01051: EndCharPtr = DateTime.ParseFormat (BeginCharPtr, DateFormatString);
01052: if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01053: {
01054: return true;
01055: }
01056:
01057: // try to parse with weekday removed from long format string:
01058: wxString WithoutWeekdayDateFormatString;
01059: if (removeWeekdayFromDateFormatString (DateFormatString,
01060: WithoutWeekdayDateFormatString))
01061: {
01062: const char * EndCharPtr = DateTime.ParseFormat (BeginCharPtr,
01063: WithoutWeekdayDateFormatString);
01064: if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01065: {
01066: return true;
01067: }
01068: }
01069:
01070: // try to parse input date in ISO-8601 format (e.g. 2004-06-01)
01071: // WARN
01072: // - Danish locale (and some others) may use %d-%m-%y as short date format,
01073: // so this may be ambiguous with ISO-8601 %Y-%m-%d
01074: // - at least, it would be wise not to use ISO-8601 with a two-digit year
01075: wxString ISO8601DateFormatString = "%Y-%m-%d";
01076: int DummyYear = 0;
01077: int ParsedYearDigits = 0;
01078: if ((wxSscanf (BeginCharPtr, "%d%n-", & DummyYear, & ParsedYearDigits) >= 1)
01079: && ParsedYearDigits == 4)
01080: {
01081: EndCharPtr = DateTime.ParseFormat (BeginCharPtr, ISO8601DateFormatString);
01082: if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01083: {
01084: return true;
01085: }
01086: }
01087:
01088: return false;
01089: }
01090:
01091: //-------------------------------------------------------------------------
01092:
01093: bool parseDateTimeWithFormat (const wxString & InputString, wxDateTime & DateTime,
01094: const wxString & DateTimeFormatString)
01095: {
01096: const char * BeginCharPtr = InputString.c_str();
01097: const char * EndCharPtr = NULL;
01098: {
01099: // use a different default date/time than default argument for
01100: // ParseFormat() to get more deterministic behavior (default would
01101: // be otherwise wxDateTime::Today())
01102: wxDateTime DefaultDateTime = wxDateTime (1, wxDateTime::Jan, 1970);
01103:
01104: EndCharPtr = DateTime.ParseFormat (BeginCharPtr, DateTimeFormatString,
01105: DefaultDateTime);
01106: if (!((EndCharPtr == NULL) || (EndCharPtr == BeginCharPtr) || (*EndCharPtr != 0)))
01107: {
01108: return true;
01109: }
01110: }
01111: return false;
01112: }
01113:
01114: void formatDateTimeWithFormat (const wxDateTime & DateTime, wxString & String,
01115: const wxString & DateTimeFormatString)
01116: {
01117: String = DateTime.Format (DateTimeFormatString);
01118: }
01119:
01120: //-------------------------------------------------------------------------
01121:
01122: bool parseDateTimeFromISOFormat (const wxString & InputString, wxDateTime & DateTime)
01123: {
01124: // try to parse input date in ISO-8601 format (e.g. 2004-06-01)
01125: // WARN
01126: // - Danish locale (and some others) may use %d-%m-%y as short date format,
01127: // so this may be ambiguous with ISO-8601 %Y-%m-%d
01128: // - at least, it would be wise not to use ISO-8601 with a two-digit year
01129: wxString ISODateTimeFormatString = "%Y-%m-%d %H:%M:%S";
01130: return parseDateTimeWithFormat (InputString, DateTime,
01131: ISODateTimeFormatString);
01132: }
01133:
01134: void formatDateTimeInISOFormat (const wxDateTime & DateTime, wxString & String)
01135: {
01136: String = "";
01137: String
01138: << DateTime.FormatISODate() << " " << DateTime.FormatISOTime();
01139: }
01140:
01141:
01142: //=========================================================================
01143:
01144: void fitInside (const wxRect & FrameRect, const wxSize & ObjectSize,
01145: wxRect & FittedObjectRect, int AlignmentFlags)
01146: {
01147: int FrameRectWidth = FrameRect.GetWidth();
01148: int FrameRectHeight = FrameRect.GetHeight();
01149: int FittedX = FrameRect.GetX();
01150: int FittedY = FrameRect.GetY();
01151: int FittedWidth;
01152: int FittedHeight;
01153: double FrameRectWidthHeightRatio = (double) FrameRectWidth
01154: / (double) FrameRectHeight;
01155: double ObjectWidthHeightRatio = (double) ObjectSize.GetWidth()
01156: / (double) ObjectSize.GetHeight();
01157:
01158: if (FrameRectWidthHeightRatio > ObjectWidthHeightRatio)
01159: {
01160: cast_round_assign (FittedWidth, FrameRectHeight * ObjectWidthHeightRatio);
01161: FittedHeight = FrameRectHeight;
01162:
01163: if (AlignmentFlags & wxALIGN_CENTER_HORIZONTAL)
01164: {
01165: FittedX += (FrameRectWidth - FittedWidth) / 2;
01166: }
01167: else if (AlignmentFlags & wxALIGN_RIGHT)
01168: {
01169: FittedX += (FrameRectWidth - FittedWidth);
01170: }
01171: }
01172: else
01173: {
01174: FittedWidth = FrameRectWidth;
01175: cast_round_assign (FittedHeight, FrameRectWidth * 1/ObjectWidthHeightRatio);
01176:
01177: if (AlignmentFlags & wxALIGN_CENTER_VERTICAL)
01178: {
01179: FittedY += (FrameRectHeight - FittedHeight) / 2;
01180: }
01181: else if (AlignmentFlags & wxALIGN_BOTTOM)
01182: {
01183: FittedY += (FrameRectHeight - FittedHeight);
01184: }
01185: }
01186:
01187: FittedObjectRect = wxRect (FittedX, FittedY, FittedWidth, FittedHeight);
01188: }
01189:
01190: //=========================================================================
01191:
01192: void makePath (const wxString & LhsPathString,
01193: const wxString & RhsPathString,
01194: wxString & ResultPathString,
01195: wxPathFormat LhsPathFormat,
01196: wxPathFormat RhsPathFormat,
01197: wxPathFormat ResultPathFormat)
01198: {
01199: wxFileName FileName (RhsPathString, RhsPathFormat);
01200: // alternative could be to use wxFileName::AppendDir() or
01201: // wxFileName::PrependDir()
01202: FileName.MakeAbsolute (LhsPathString, LhsPathFormat);
01203: ResultPathString = FileName.GetFullPath (ResultPathFormat);
01204: }
01205:
01206: wxString makePath (const wxString & LhsPathString,
01207: const wxString & RhsPathString,
01208: wxPathFormat LhsPathFormat,
01209: wxPathFormat RhsPathFormat,
01210: wxPathFormat ResultPathFormat)
01211: {
01212: wxString ResultString;
01213: makePath (LhsPathString,
01214: RhsPathString,
01215: ResultString,
01216: LhsPathFormat,
01217: RhsPathFormat,
01218: ResultPathFormat);
01219: return ResultString;
01220: }
01221:
01222: //-------------------------------------------------------------------------
01223:
01224: void makeAbsolutePath (const wxString & RelativeOrAbsolutePathString,
01225: const wxString & ReferenceDirString,
01226: wxString & AbsolutePathString,
01227: wxPathFormat RelativeOrAbsolutePathFormat,
01228: wxPathFormat ReferenceDirFormat,
01229: wxPathFormat AbsolutePathFormat)
01230: {
01231: wxFileName FileName (RelativeOrAbsolutePathString, RelativeOrAbsolutePathFormat);
01232: // alternative could be to use wxFileName::AppendDir() or
01233: // wxFileName::PrependDir()
01234: FileName.MakeAbsolute (ReferenceDirString, ReferenceDirFormat);
01235: AbsolutePathString = FileName.GetFullPath (AbsolutePathFormat);
01236: }
01237:
01238: wxString makeAbsolutePath (const wxString & RelativeOrAbsolutePathString,
01239: const wxString & ReferenceDirString,
01240: wxPathFormat RelativeOrAbsolutePathFormat,
01241: wxPathFormat ReferenceDirFormat,
01242: wxPathFormat AbsolutePathFormat)
01243: {
01244: wxString AbsolutePathString;
01245: makeAbsolutePath (RelativeOrAbsolutePathString,
01246: ReferenceDirString,
01247: AbsolutePathString,
01248: RelativeOrAbsolutePathFormat,
01249: ReferenceDirFormat,
01250: AbsolutePathFormat);
01251: return AbsolutePathString;
01252: }
01253:
01254: //-------------------------------------------------------------------------
01255:
01256: void makeRelativePath (const wxString & RelativeOrAbsolutePathString,
01257: const wxString & ReferenceDirString,
01258: wxString & RelativePathString,
01259: bool IsUseRelativeParentDir,
01260: wxPathFormat RelativeOrAbsolutePathFormat,
01261: wxPathFormat ReferenceDirFormat,
01262: wxPathFormat RelativePathFormat)
01263: {
01264: wxFileName FileName (RelativeOrAbsolutePathString, RelativeOrAbsolutePathFormat);
01265: FileName.MakeRelativeTo (ReferenceDirString, ReferenceDirFormat);
01266:
01267: if ((!IsUseRelativeParentDir)
01268: && (FileName.GetFullPath().StartsWith ("..")))
01269: {
01270: RelativePathString = RelativeOrAbsolutePathString;
01271: }
01272: else
01273: {
01274: RelativePathString = FileName.GetFullPath (RelativePathFormat);
01275: }
01276: }
01277:
01278: wxString makeRelativePath (const wxString & RelativeOrAbsolutePathString,
01279: const wxString & ReferenceDirString,
01280: bool IsUseRelativeParentDir,
01281: wxPathFormat RelativeOrAbsolutePathFormat,
01282: wxPathFormat ReferenceDirFormat,
01283: wxPathFormat RelativePathFormat)
01284: {
01285: wxString RelativePathString;
01286: makeRelativePath (RelativeOrAbsolutePathString,
01287: ReferenceDirString,
01288: RelativePathString,
01289: IsUseRelativeParentDir,
01290: RelativeOrAbsolutePathFormat,
01291: ReferenceDirFormat,
01292: RelativePathFormat);
01293: return RelativePathString;
01294: }
01295:
01296: //-------------------------------------------------------------------------
01297:
01298: void addConcatenatedStrings (const wxArrayString & StringArray,
01299: wxString & OutputString,
01300: const wxString & ElementPrefixString,
01301: const wxString & ElementPostfixString,
01302: const wxString & InfixString)
01303: {
01304: int Count = StringArray.GetCount();
01305: bool IsElementPrefix = !ElementPrefixString.IsEmpty();
01306: bool IsElementPostfix = !ElementPostfixString.IsEmpty();
01307: // bool IsInfix = !InfixString.IsEmpty();
01308: for (int Index = 0; Index < Count; ++Index)
01309: {
01310: if (Index > 0)
01311: OutputString << InfixString;
01312:
01313: if (IsElementPrefix)
01314: OutputString << ElementPrefixString;
01315:
01316: OutputString << StringArray.Item(Index);
01317:
01318: if (IsElementPostfix)
01319: OutputString << ElementPostfixString;
01320: }
01321: }
01322:
01323: //-------------------------------------------------------------------------
01324:
01325: const char * wxGetIdTranslation(const char * MessageIdentCharPtr, const char * DefaultCharPtr)
01326: {
01327: const char * TranslatedCharPtr = wxGetTranslation (MessageIdentCharPtr);
01328: const char CheckedPrefixCharArray [] = "{id:";
01329: // TODO: could replace strncmp() with string pointer comparison to detect
01330: // if a translation is available
01331: if (strncmp (TranslatedCharPtr, CheckedPrefixCharArray,
01332: WXSIZEOF(CheckedPrefixCharArray) - 1) == 0)
01333: {
01334: return DefaultCharPtr;
01335: }
01336: else
01337: {
01338: return TranslatedCharPtr;
01339: }
01340: }
01341:
01342: //-------------------------------------------------------------------------
01343:
01344: const char * wxGetCatalogMetaData(const char * MessageIdentCharPtr)
01345: {
01346: const char * TranslatedCharPtr = wxGetTranslation (MessageIdentCharPtr);
01347: if (TranslatedCharPtr == MessageIdentCharPtr)
01348: {
01349: return NULL;
01350: }
01351: else
01352: {
01353: return TranslatedCharPtr;
01354: }
01355: }
01356:
01357: //-------------------------------------------------------------------------
01358:
01359: wxCatalogAddManag::wxCatalogAddManag()
01360: {
01361: init();
01362: }
01363:
01364: void wxCatalogAddManag::init ()
01365: {
01366: m_IsError = false;
01367: }
01368:
01369: void wxCatalogAddManag::setLocale (wxLocale * Locale)
01370: {
01371: m_Locale = Locale;
01372: }
01373:
01374: bool wxCatalogAddManag::addCatalog (const wxString & CatalogName)
01375: {
01376: if (m_Locale -> GetLanguage() == wxLANGUAGE_UNKNOWN)
01377: {
01378: // don't try to load catalogue if language is not set or known
01379: }
01380: else
01381: {
01382: if (!m_Locale -> AddCatalog (CatalogName))
01383: {
01384: m_IsError = true;
01385: // m_MessageString << "failed to load catalog \"" << CatalogName << "\".\n";
01386: m_MessageString << CatalogName << ":\n" << " failed to load catalogue\n";
01387: return false;
01388: }
01389: // else
01390: // m_MessageString << CatalogName << ": loaded\n";
01391: }
01392:
01393: return true;
01394: }
01395:
01396: bool wxCatalogAddManag::addCatalogWithVersionCheck (const wxString & CatalogName,
01397: const wxString & RequiredVersionString)
01398: {
01399: if (m_Locale -> GetLanguage() == wxLANGUAGE_UNKNOWN)
01400: {
01401: // don't try to load catalogue if language is not set or known
01402: }
01403: else if (addCatalog (CatalogName))
01404: {
01405: wxString VersionMessageIdentString = wxString("{meta:") + CatalogName + ":VersionIdent}";
01406: const char * ActualVersionString = wxGetCatalogMetaData (VersionMessageIdentString);
01407:
01408: if ((ActualVersionString == NULL)
01409: || (strcmp (ActualVersionString, RequiredVersionString) != 0))
01410: {
01411: m_MessageString
01412: << CatalogName << ":\n"
01413: << " required version: " << RequiredVersionString << "\n"
01414: << " actual version: " << ((ActualVersionString != NULL) ? ActualVersionString : "(unknown)")
01415: << "\n";
01416:
01417: m_IsError = true;
01418: }
01419:
01420: return false;
01421: }
01422:
01423: return true;
01424: }
01425:
01426: bool wxCatalogAddManag::getMessage (wxString & MessageString)
01427: {
01428: if (true)
01429: {
01430: int LanguageId = m_Locale -> GetLanguage();
01431: const struct wxLanguageInfo * LanguageInfoPtr = wxLocale::GetLanguageInfo (LanguageId);
01432: MessageString << "Language: ";
01433: if (LanguageInfoPtr != NULL)
01434: {
01435: MessageString
01436: << LanguageInfoPtr->Description << " (" << LanguageInfoPtr->CanonicalName << ")\n\n";
01437: }
01438: else
01439: {
01440: MessageString << "(unknown)" << "\n\n";
01441: }
01442: }
01443:
01444: if (m_IsError)
01445: {
01446: MessageString
01447: << "Some of the message translation catalogues could not be loaded "
01448: << "or do not have the expected versions:\n\n";
01449: }
01450:
01451: // output messages about specific language versions
01452: MessageString << m_MessageString;
01453:
01454: return (m_IsError);
01455: }
01456:
01457:
01458: #if 0
01459: extern bool checkCatalogueMetaData (wxString & MessageString,
01460: const char * CatalogueNameString,
01461: const char * VersionMessageIdentCharPtr,
01462: const char * RequiredVersionString)
01463: {
01464: bool IsOkay = false;
01465: const char * ActualVersionString = wxGetCatalogueMetaData (VersionMessageIdentCharPtr);
01466:
01467: #if 0
01468: MessageString
01469: << VersionMessageIdentCharPtr << ":\n"
01470: << " required value: " << RequiredVersionString << "\n"
01471: << " actual value: " << ((ActualVersionString != NULL) ? ActualVersionString : "(not found)") << "";
01472: #endif
01473: MessageString
01474: << CatalogueNameString << ":\n"
01475: << " required version: " << RequiredVersionString << "\n"
01476: << " actual version: " << ((ActualVersionString != NULL) ? ActualVersionString : "(not found)") << "";
01477:
01478: if (ActualVersionString == NULL)
01479: {
01480: #if 0
01481: MessageString
01482: << "could not find entry for meta-data key \"" << VersionMessageIdentCharPtr << "\" "
01483: << "in message catalogue \"" << CatalogueNameString << "\", "
01484: << "which must match \"" << RequiredVersionString << "\" ";
01485: #endif
01486: }
01487: else
01488: {
01489: if (strcmp (ActualVersionString, RequiredVersionString) != 0)
01490: {
01491: #if 0
01492: MessageString
01493: << "entry for meta-data \"" << VersionMessageIdentCharPtr << "\" "
01494: << "in message catalogue " << CatalogueNameString << ", "
01495: << "which must match \"" << RequiredVersionString << "\" "
01496: << "has a value of \"" << ActualVersionString << "\" ";
01497: #endif
01498: }
01499: else
01500: {
01501: #if 0
01502: MessageString
01503: << "entry for meta-data \"" << VersionMessageIdentCharPtr << "\" "
01504: << "in message catalogue " << CatalogueNameString << ", "
01505: << "matches required value of \"" << RequiredVersionString << "\" ";
01506: #endif
01507: IsOkay = true;
01508: }
01509: }
01510: MessageString << "\n\n";
01511: return IsOkay;
01512: }
01513: #endif
01514:
01515: //=========================================================================
01516:
01517: #if defined(__WXMSW__)
01518:
01519: // // wxGetInstance() is somehow needed for loadDataResource():
01520: // // (as declared in ./include/wx/msw/private.h):
01521: // WXDLLEXPORT HINSTANCE wxGetInstance();
01522: // NOTE we use GetModuleHandle(NULL) instead of wxGetInstance()
01523: // which may not work under Win16
01524:
01525: // NOTE semantics not well defined for Win16: there, some function like
01526: // releaseDataResource() or copying the data block would be needed
01527: bool loadDataResource (const wxString & ResourceNameString,
01528: const char * ResourceTypeString,
01529: unsigned char ** DataPtr, size_t * DataSize)
01530: {
01531: bool IsCompleted = false;
01532:
01533: for_once
01534: {
01535: HRSRC ResourceHandle = ::FindResource (::GetModuleHandle(NULL) /*wxGetInstance()*/,
01536: ResourceNameString, ResourceTypeString);
01537: if (ResourceHandle == 0)
01538: break;
01539:
01540: HGLOBAL DataHandle = NULL;
01541: if (DataPtr != NULL)
01542: {
01543: // load and lock data block (if desired, i.e. if DataPtr != NULL)
01544: DataHandle = ::LoadResource (::GetModuleHandle(NULL) /*wxGetInstance()*/,
01545: ResourceHandle);
01546: if (DataHandle == 0)
01547: break;
01548:
01549: *DataPtr = (unsigned char *) ::LockResource (DataHandle);
01550: if (*DataPtr == NULL)
01551: break;
01552: }
01553:
01554: if (DataSize != NULL)
01555: {
01556: // determine size of the data block (if desired)
01557: *DataSize = ::SizeofResource (GetModuleHandle (NULL) /*wxGetInstance()*/,
01558: ResourceHandle);
01559: }
01560:
01561: // BUG for Win16:
01562: // UnlockResource() must be called for Win16, however; we must
01563: // probably do this after working with the data
01564:
01565: IsCompleted = true;
01566: }
01567:
01568: return IsCompleted;
01569: }
01570:
01571: // void releaseDataResource ()
01572: // {
01573: // if (DataPtr != NULL)
01574: // {
01575: // // UnlockResource() not needed for WIN32
01576: // #ifndef __WIN32__
01577: // UnlockResource(DataHandle);
01578: // #endif
01579: // }
01580:
01581: // // needed for Win16?
01582: // // GlobalFree(hData);
01583: // }
01584:
01585: #endif // defined(__WXMSW__)
01586:
01587: //=========================================================================
01588:
01589: // bool loadFile (const wxString & FileNameString,
01590: // wxByteArray & ByteArray)
01591: // {
01592: // ByteArray.Clear();
01593: // ByteArray
01594: // wxFileInputStream FileInputStream = wxFileInputStream (FilenameString);
01595: //
01596: // if (!(FileInputStream -> Ok()))
01597: // return false;
01598: //
01599: // FileInputStream.Read (ByteArray, ByteCount);
01600: //
01601: // }
01602:
01603: //-------------------------------------------------------------------------
01604:
01605: // WARN why conditional compilation only for wxGUI here?
01606: #if wxUSE_GUI
01607: bool loadImageFromMemory (const unsigned char * ImageData, size_t ImageDataSize,
01608: wxImage & Image)
01609: {
01610: wxMemoryInputStream MemoryInputStream (ImageData, ImageDataSize);
01611: return Image.LoadFile (MemoryInputStream);
01612: }
01613:
01614: bool loadBitmapFromMemory (const unsigned char * ImageData, size_t ImageDataSize,
01615: wxBitmap ** Bitmap)
01616: {
01617: *Bitmap = NULL;
01618:
01619: bool IsOk = false;
01620: for_once
01621: {
01622: wxImage Image;
01623: if (! loadImageFromMemory (ImageData, ImageDataSize, Image))
01624: break;
01625:
01626: *Bitmap = new wxBitmap (Image);
01627: if (*Bitmap == NULL)
01628: break;
01629:
01630: IsOk = true;
01631: }
01632:
01633: return IsOk;
01634: }
01635: #endif // wxUSE_GUI
01636:
01637: #if defined(__WXMSW__)
01638:
01639: #if wxUSE_GUI
01640: bool loadImageFromResource (const wxString & ImageDataResourceNameString,
01641: wxImage & Image)
01642: {
01643: unsigned char * DataPtr = NULL;
01644: size_t DataSize = 0;
01645: if (!loadDataResource (ImageDataResourceNameString, RT_RCDATA,
01646: & DataPtr, & DataSize))
01647: return false;
01648:
01649: return loadImageFromMemory (DataPtr, DataSize, Image);
01650: }
01651:
01652: bool loadBitmapFromResource (const wxString & ImageDataResourceNameString,
01653: wxBitmap ** Bitmap)
01654: {
01655: bool IsOk = false;
01656:
01657: *Bitmap = NULL;
01658:
01659: for_once
01660: {
01661: unsigned char * DataPtr = NULL;
01662: size_t DataSize = 0;
01663: if (!loadDataResource (ImageDataResourceNameString, RT_RCDATA,
01664: & DataPtr, & DataSize))
01665: break;
01666:
01667: if (!loadBitmapFromMemory (DataPtr, DataSize, Bitmap))
01668: break;
01669:
01670: IsOk = true;
01671: }
01672:
01673: if (!IsOk)
01674: *Bitmap = new wxBitmap ();
01675:
01676: return IsOk;
01677: }
01678: #endif // wxUSE_GUI
01679:
01680: #endif // defined(__WXMSW__)
01681:
01682: //=========================================================================
01683:
01684: #if (M_WxExtLib_IsUseGraphicsHelper == 1)
01685: # if wxUSE_GUI
01686:
01687: // resizeImageVGrid()
01688: // Todo:
01689: // - support wxImage having alpha/transparency channel (wxWidgets
01690: // version approx. >= 2.5)
01691: // - check version numbers wxImage/wxCHECK_VERSION switching
01692: bool resizeImageVGrid (const wxImage & InputImage,
01693: wxImage & OutputImage,
01694: int OutputWidth, int OutputHeight)
01695: {
01696: if (!InputImage.Ok())
01697: return false;
01698:
01699: #if wxCHECK_VERSION (2, 5, 0)
01700: if (!OutputImage.Create (OutputWidth, OutputHeight, false /* IsClear */))
01701: return false;
01702: #else
01703: // overload resolution for older version may accidently interpret 'false'
01704: // as pointer and so use Create() with initialization of allocated bytes:
01705: OutputImage.Create (OutputWidth, OutputHeight);
01706: #endif
01707:
01708: if (!OutputImage.Ok())
01709: return false;
01710:
01711: const unsigned char * InputImageData = InputImage.GetData();
01712: unsigned char * OutputImageData = OutputImage.GetData();
01713:
01714: #if wxCHECK_VERSION (2, 5, 0)
01715: if (InputImage.HasAlpha())
01716: return false;
01717: #endif
01718:
01719: if (!resizeImageVGrid (InputImageData, InputImage.GetWidth() * 3,
01720: InputImage.GetWidth(), InputImage.GetHeight(),
01721: true /* IsRGB */ , false /* IsAlpha */,
01722: OutputImageData, OutputImage.GetWidth() * 3,
01723: OutputImage.GetWidth(), OutputImage.GetHeight()))
01724: return false;
01725:
01726: return true;
01727: }
01728: # endif
01729: #endif
01730:
01731: //=========================================================================
01732:
01733: // doTextLineWrap()
01734: // - text extents are calculated for the font currently set for the DC
01735: // Possible improvements:
01736: // - Insert e.g. '\r\n' or '\r\r\n' when having a 'soft' line break (not forced)
01737: // instead of just '\n'. This way, the soft line breaks could be un-done
01738: // again (because then they would be distinguishable from the hard line breaks).
01739: // This could be useful if a control want's to re-do line wrapping
01740: // e.g. after a size change notification.
01741: void doTextLineWrap (const wxString & InputString,
01742: int MaxLineWidth,
01743: wxDC & DC,
01744: wxString & ResultString)
01745: {
01746: wxString CurrentLineString;
01747: // pre-allocate line-string to improve performance:
01748: CurrentLineString.Alloc (512);
01749:
01750: const char * CurrentCharPtr = InputString.c_str();
01751: // const char * LineStartCharPtr = CurrentCharPtr;
01752: const char * LastBreakCharPtr = NULL;
01753:
01754: int CurrentLineCharCount = 0;
01755: int LastBreakCharCount = 0;
01756:
01757: bool IsJustAfterWrap;
01758: bool IsAfterWrap = false;
01759: while (1)
01760: {
01761: IsJustAfterWrap = false;
01762: bool IsBreakAllowed = false;
01763: bool IsBreakForced = false;
01764:
01765: int CurrentChar = *CurrentCharPtr;
01766:
01767: if (IsAfterWrap)
01768: {
01769: if (!(CurrentChar == '\0'
01770: || wxIsspace (CurrentChar))
01771: || CurrentChar == '\n')
01772: IsAfterWrap = false;
01773: }
01774:
01775: if (!IsAfterWrap)
01776: {
01777: if (CurrentChar == '\0'
01778: || wxIsspace (CurrentChar))
01779: IsBreakAllowed = true;
01780:
01781: if (CurrentChar == '\n'
01782: || CurrentChar == '\0')
01783: IsBreakForced = true;
01784: }
01785:
01786: if (IsBreakAllowed
01787: || IsBreakForced)
01788: {
01789: int Width = 0;
01790: int Height = 0;
01791: // NOTE there is also wxWindow::GetTextExtent, maybe
01792: // one could optionally use this function instead of wxDC::GetTextExtent
01793: DC.GetTextExtent (CurrentLineString, & Width, & Height);
01794:
01795: bool IsOverfull = (Width > MaxLineWidth);
01796:
01797: if (IsOverfull
01798: || IsBreakForced)
01799: {
01800: const char * ActualBreakCharPtr = NULL;
01801: if (IsOverfull)
01802: {
01803: ActualBreakCharPtr = LastBreakCharPtr;
01804: if (ActualBreakCharPtr == NULL)
01805: ActualBreakCharPtr = CurrentCharPtr;
01806: }
01807: else
01808: {
01809: ActualBreakCharPtr = CurrentCharPtr;
01810: }
01811:
01812: if (IsOverfull
01813: && LastBreakCharPtr != NULL)
01814: {
01815: CurrentLineString.Truncate (LastBreakCharCount);
01816: }
01817:
01818: ResultString.Append (CurrentLineString);
01819: ResultString.Append ("\n");
01820:
01821: // set string to empty but retain allocated memory:
01822: CurrentLineString.Empty ();
01823:
01824: // reposition pointers
01825: // LineStartCharPtr = ActualBreakCharPtr;
01826: CurrentCharPtr = ActualBreakCharPtr;
01827: CurrentChar = *CurrentCharPtr;
01828: LastBreakCharPtr = NULL;
01829: LastBreakCharCount = 0;
01830: CurrentLineCharCount = 0;
01831:
01832: if (CurrentChar == '\n')
01833: {
01834: ++CurrentCharPtr;
01835: CurrentChar = *CurrentCharPtr;
01836: }
01837:
01838: IsAfterWrap = true;
01839: IsJustAfterWrap = true;
01840: }
01841: else
01842: {
01843: LastBreakCharPtr = CurrentCharPtr;
01844: LastBreakCharCount = CurrentLineCharCount;
01845: }
01846: }
01847:
01848: if (CurrentChar == '\0')
01849: break;
01850:
01851: if (!IsAfterWrap)
01852: {
01853: CurrentLineString.Append ((char) CurrentChar);
01854: ++CurrentLineCharCount;
01855: }
01856:
01857: if (!IsJustAfterWrap)
01858: {
01859: ++CurrentCharPtr;
01860: }
01861: }
01862: }
01863:
01864: //-------------------------------------------------------------------------
01865:
01866: void doTextLineWrap (const wxString & InputString,
01867: int MaxLineWidth,
01868: wxWindow * Window,
01869: wxString & ResultString)
01870: {
01871: wxClientDC ClientDC (Window);
01872: const wxFont & Font = Window -> GetFont ();
01873:
01874: ClientDC.SetFont (Font);
01875: doTextLineWrap (InputString, MaxLineWidth, ClientDC, ResultString);
01876:
01877: // WARN don't know if resetting old font is required
01878: }
01879:
01880: //=========================================================================
01881:
01882: bool wxVerifyWindowPtr (wxWindow * ParentWindow, wxWindow * SearchedWindow)
01883: {
01884: wxWindowListNode * Node = NULL;
01885:
01886: if (ParentWindow == SearchedWindow)
01887: return true;
01888:
01889: // search list of windows recursively, starting from specified
01890: // ParentWindow, depth-first search
01891: for (Node = ParentWindow->GetChildren().GetFirst();
01892: Node != NULL;
01893: Node = Node->GetNext())
01894: {
01895: wxWindow * Window = Node->GetData();
01896: bool IsFound = wxVerifyWindowPtr (Window, SearchedWindow);
01897: if (IsFound)
01898: return true;
01899: }
01900:
01901: return false;
01902: }
01903:
01904: //=========================================================================
01905:
01906: wxFocusRestorer::wxFocusRestorer ()
01907: {
01908: m_OldFocusWindow = wxWindow::FindFocus ();
01909:
01910: // save HWND?
01911: // HWND m_OldFocusHwnd = OldFocusWindow != NULL ? GetHwndOf (OldFocusWindow) : NULL;
01912: }
01913:
01914: wxFocusRestorer::~wxFocusRestorer ()
01915: {
01916: if (m_OldFocusWindow != NULL)
01917: {
01918: wxWindow * CurrentFocusWindow = wxWindow::FindFocus ();
01919:
01920: // TEST: set focus window only if it appears to have changed
01921: // to avoid flicker (if this is the reason for flicker, maybe
01922: // it isn't)
01923: if (CurrentFocusWindow != m_OldFocusWindow)
01924: m_OldFocusWindow -> SetFocus();
01925: }
01926: }
01927:
01928: //=========================================================================
01929:
01930: #if wxUSE_GUI
01931: wxMultiLineText::wxMultiLineText ()
01932: {
01933: m_TextCtrl = NULL;
01934: m_HtmlWindow = NULL;
01935: m_StaticText = NULL;
01936:
01937: m_MultiLineTextStyle = 0;
01938: }
01939:
01940: void wxMultiLineText::create (wxWindow * ParentWindow,
01941: int WindowIdent,
01942: int CtrlStyle,
01943: const wxSize & MinSize,
01944: int MultiLineTextStyle)
01945: {
01946: wxSize UsedSize = MinSize;
01947:
01948: m_MultiLineTextStyle = MultiLineTextStyle;
01949:
01950: // determine what kind of borders to use:
01951: if (! (CtrlStyle & wxBORDER_NONE)
01952: && !(CtrlStyle & wxBORDER_SIMPLE))
01953: {
01954: // default is wxSUNKEN_BORDER:
01955: CtrlStyle |= wxSUNKEN_BORDER;
01956: }
01957:
01958: // determine if wxTextCtrl or wxHtmlWindow should be used:
01959: bool IsCreateTextCtrl = true;
01960:
01961: #if ((defined __WXMOTIF__) || defined(__WXGTK__))
01962: // with Lesstif/Motif?, we don't want to use wxTextCtrl
01963: // because it uses a fixed-size typewriter-like font
01964: // and setting colours is not possible
01965: //
01966: // GTK (1.2.7) wxTextCtrl ignores setting foreground, background
01967: // colours or not using sunken border
01968: //
01969: // default for Motif/Lesstif, GTK: use wxHtmlWindow
01970: IsCreateTextCtrl = false;
01971: #endif
01972:
01973: if (MultiLineTextStyle & wxFORCE_HTMLWINDOW)
01974: IsCreateTextCtrl = false;
01975:
01976: if (MultiLineTextStyle & wxFORCE_TEXTCTRL)
01977: IsCreateTextCtrl = true;
01978:
01979: if (MultiLineTextStyle & wxHTML_MODE)
01980: IsCreateTextCtrl = false;
01981:
01982: // create the desired control type
01983: if (IsCreateTextCtrl)
01984: {
01985: // borders: wxTextCtrl seems to normally have a border.
01986: // No border can be requested with wxBORDER_NONE.
01987:
01988: long TextCtrlStyle = wxTE_MULTILINE | wxTE_LINEWRAP | wxTE_READONLY;
01989: /* | wxVSCROLL | wxTE_RICH | wxBORDER_NONE */
01990: // if (! (CtrlStyle & wxSUNKEN_BORDER))
01991: // TextCtrlStyle |= wxBORDER_NONE;
01992: TextCtrlStyle |= CtrlStyle;
01993:
01994: m_TextCtrl = new wxTextCtrl (ParentWindow, WindowIdent, _T(""),
01995: wxDefaultPosition, UsedSize,
01996: TextCtrlStyle,
01997: wxDefaultValidator);
01998:
01999: m_TextCtrl -> SetBackgroundColour (ParentWindow -> GetBackgroundColour());
02000: }
02001: else
02002: {
02003: // borders: wxHtmlWindow seems to support
02004: // wxSIMPLE_BORDER, wxSUNKEN_BORDER, (no border if no flag specified),
02005: // maybe others
02006: m_HtmlWindow = new wxHtmlWindow (ParentWindow, WindowIdent,
02007: wxDefaultPosition,
02008: UsedSize,
02009: CtrlStyle);
02010: m_HtmlWindow -> SetBorders (2);
02011: m_HtmlWindow -> SetBackgroundColour (ParentWindow -> GetBackgroundColour());
02012: }
02013:
02014: // // wxStaticText apparently ignores wxVSCROLL (at least under
02015: // // this X11 and this Lesstif), so it isn't very useful for our cause
02016: // // of displaying, possibly very long, multi-line text
02017: // m_StaticText = new wxStaticText (ParentWindow, WindowIdent, _T(""),
02018: // wxDefaultPosition, UsedSize,
02019: // /* WindowStyle */ wxVSCROLL);
02020:
02021: }
02022:
02023: //-------------------------------------------------------------------------
02024:
02025: void wxMultiLineText::setText (const wxString & String)
02026: {
02027: if (m_TextCtrl != NULL)
02028: {
02029: #if defined(__WXMSW__)
02030: // the RichEdit supports line wrapping
02031: m_TextCtrl -> SetValue (String);
02032: #else
02033: // under X11, the wxTextCtrl doesn't support wrapping of long
02034: // lines by itself, here we call doTextLineWrap()
02035: // (note: from wxWindows 2.6 (2.5.x) on, the wxX11/wxUniv wxTextCtrl
02036: // will have support for line wrap)
02037: //
02038: // GTK 1.x: the wxTextCtrl supports wxTE_LINEWRAP, but
02039: // wxTextCtrl::GetNumberOfLines() only counts newlines
02040: // (but we are interessted in the number of lines after
02041: // doing the wrapping) - because of this problem, we use
02042: // doTextLineWrap() for GTK as well
02043: //
02044: wxSize ClientSize = m_TextCtrl -> GetClientSize();
02045: wxString ResultString;
02046:
02047: int MaxLineWidth = ClientSize.GetWidth();
02048: // HACK quick hack to account for possibly existing
02049: // scrollbars:
02050: if (MaxLineWidth >= 25)
02051: MaxLineWidth -= 25;
02052:
02053: #if defined(__WXMOTIF__)
02054: // the Lesstif wxTextCtrl has lot's of bordering around the
02055: // space actually usable for text, so subtract a little from
02056: // the horizontal size
02057: MaxLineWidth -= 20;
02058: #endif
02059:
02060: // NOTE: the wxUniversal wxTextCtrl now (version 2.5.2 tested) has support
02061: // for wrapping long lines, so calling doTextLineWrap() may not be required
02062: // for this newer wxWindows versions
02063: // Also, this new wrapping mechanism has support for partial re-wrapping,
02064: // which is not available with doTextLineWrap().
02065: // (however, must check semantics of GetNumberOfLines())
02066: doTextLineWrap (String, MaxLineWidth,
02067: m_TextCtrl,
02068: ResultString);
02069: m_TextCtrl -> SetValue (ResultString);
02070: #endif
02071: }
02072: else if (m_HtmlWindow != NULL)
02073: {
02074: // WARN should add charset name in HTML <head> for currently used charset
02075: wxString HtmlString = "<html><body bgcolor=\""
02076: + formatColourToHtmlParam (m_HtmlWindow -> GetBackgroundColour())
02077: + "\" text=\""
02078: + formatColourToHtmlParam (m_HtmlWindow -> GetForegroundColour())
02079: + "\">\n"
02080: + "";
02081: if (m_MultiLineTextStyle & wxHTML_MODE)
02082: {
02083: HtmlString += String;
02084: }
02085: else
02086: {
02087: HtmlString += convertAsciiToHtml (String, true,
02088: wxAsciiToHtml_ConvertLeadingSpaces);
02089: }
02090: HtmlString += "</body></html>";
02091: m_HtmlWindow -> SetPage (HtmlString);
02092: }
02093: else if (m_StaticText != NULL)
02094: {
02095: m_StaticText -> SetLabel (String);
02096: }
02097: }
02098:
02099: //-------------------------------------------------------------------------
02100:
02101: wxWindow * wxMultiLineText::getWindow ()
02102: {
02103: if (m_TextCtrl != NULL)
02104: return m_TextCtrl;
02105: else if (m_HtmlWindow != NULL)
02106: return m_HtmlWindow;
02107: else if (m_StaticText != NULL)
02108: return m_StaticText;
02109: else
02110: return NULL;
02111: }
02112:
02113: wxTextCtrl * wxMultiLineText::getTextCtrl ()
02114: {
02115: return m_TextCtrl;
02116: }
02117:
02118: wxHtmlWindow * wxMultiLineText::getHtmlWindow ()
02119: {
02120: return m_HtmlWindow;
02121: }
02122:
02123: wxStaticText * wxMultiLineText::getStaticText ()
02124: {
02125: return m_StaticText;
02126: }
02127:
02128: //-------------------------------------------------------------------------
02129:
02130: void wxMultiLineText::setTextCtrl (wxTextCtrl * TextCtrl, int MultiLineTextStyle)
02131: {
02132: m_TextCtrl = TextCtrl;
02133: m_StaticText = NULL;
02134: m_HtmlWindow = NULL;
02135:
02136: m_MultiLineTextStyle = MultiLineTextStyle;
02137: }
02138:
02139: void wxMultiLineText::getStaticText (wxStaticText * StaticText, int MultiLineTextStyle)
02140: {
02141: m_TextCtrl = NULL;
02142: m_StaticText = StaticText;
02143: m_HtmlWindow = NULL;
02144:
02145: m_MultiLineTextStyle = MultiLineTextStyle;
02146: }
02147:
02148: void wxMultiLineText::setHtmlWindow (wxHtmlWindow * HtmlWindow, int MultiLineTextStyle)
02149: {
02150: m_TextCtrl = NULL;
02151: m_StaticText = NULL;
02152: m_HtmlWindow = HtmlWindow;
02153:
02154: m_MultiLineTextStyle = MultiLineTextStyle;
02155: }
02156: #endif // wxUSE_GUI
02157:
02158: //=========================================================================
02159:
02160: #if wxUSE_GUI
02161:
02162: IMPLEMENT_DYNAMIC_CLASS(wxTransparentStaticText, wxStaticText)
02163:
02164: BEGIN_EVENT_TABLE (wxTransparentStaticText, wxStaticText)
02165: #if defined (__WXMSW__)
02166: EVT_ERASE_BACKGROUND (wxTransparentStaticText::OnEraseBackground)
02167: EVT_PAINT(wxTransparentStaticText::OnPaint)
02168: #else
02169: // see notes below regarding transparency support in other ports
02170: // than wxMSW
02171: #endif
02172: END_EVENT_TABLE()
02173:
02174: //-------------------------------------------------------------------------
02175:
02176: wxTransparentStaticText::wxTransparentStaticText ()
02177: {
02178: }
02179:
02180: bool wxTransparentStaticText::Create(wxWindow * ParentWindow,
02181: wxWindowID ControlIdent,
02182: const wxString& LabelString,
02183: const wxPoint& Position,
02184: const wxSize& Size,
02185: long Style,
02186: ETransparentStaticTextFlags Flags,
02187: const wxString& Name)
02188: {
02189: m_TransparentStaticTextFlags = Flags;
02190:
02191: bool IsOk = wxStaticText::Create (ParentWindow, ControlIdent, LabelString,
02192: Position, Size, Style, Name);
02193:
02194: return IsOk;
02195: }
02196:
02197: //-------------------------------------------------------------------------
02198:
02199: void wxTransparentStaticText::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02200: {
02201: // background is painted in OnPaint(), to avoid flicker
02202:
02203: // doesn't exist:
02204: // wxWindow::OnEraseBackground (EraseEvent);
02205: }
02206:
02207: void wxTransparentStaticText::OnPaint (wxPaintEvent & PaintEvent)
02208: {
02209: #if defined(__WXMSW__)
02210: // wxMSW port: wxStaticText doesn't seem to support text in transparency
02211: // mode, so implement our own paint function
02212:
02213: wxPaintDC PaintWxDC (this);
02214:
02215: wxRect WindowRect = GetClientRect();
02216:
02217: if (m_TransparentStaticTextFlags & IsOpaque)
02218: {
02219: // wxDC & DC = * EraseEvent.GetDC();
02220:
02221: PaintWxDC.SetBrush (wxBrush (GetBackgroundColour(), wxSOLID));
02222: PaintWxDC.SetPen (* wxTRANSPARENT_PEN);
02223: PaintWxDC.DrawRectangle (WindowRect);
02224: }
02225:
02226: // other settings which might be important for drawing:
02227: // - SetMapMode(), SetUserScale()
02228: // - SetTextForeground()
02229: // - SetTextBackground()
02230: // - SetClippingRegion()
02231:
02232: // PaintWxDC.SetPen (m_Pen);
02233: // PaintWxDC.SetBrush (m_Brush);
02234: // PaintWxDC.DrawRectangle (WindowRect);
02235: // PaintWxDC.DrawRoundedRectangle (WindowRect, -4.0);
02236:
02237: // WARN required to set these values back?
02238: PaintWxDC.SetBackgroundMode (wxTRANSPARENT);
02239: PaintWxDC.SetTextForeground (GetForegroundColour ());
02240: PaintWxDC.SetTextBackground (GetBackgroundColour ());
02241: PaintWxDC.SetFont (GetFont ());
02242:
02243: // DC::DrawText() seems to ignore ampersand characters, so use
02244: // Win32 API DrawText() instead
02245: // PaintWxDC.DrawText (wxGetWindowText(GetHWND()), WindowRect.GetX(), WindowRect.GetY());
02246: wxString WindowTextString = GetLabel();
02247:
02248: // const char * WindowTextCharPtr = WindowTextString.c_str();
02249: int CharCount = wxStrlen (WindowTextString);
02250:
02251: // GetPixel returns a COLORREF in Win32
02252: COLORREF ForegroundColorRef = GetForegroundColour().GetPixel();
02253:
02254: HDC PaintDC = (HDC) PaintWxDC.GetHDC();
02255: COLORREF PreviousForegroundColorRef = SetTextColor (PaintDC, ForegroundColorRef);
02256: int PreviousBkMode = SetBkMode (PaintDC, TRANSPARENT);
02257:
02258: // BUG TODO
02259: // HDC SetFont
02260: // test/compile with other wx ports
02261:
02262: RECT Rect = {WindowRect.GetX(), WindowRect.GetY(),
02263: WindowRect.GetWidth(), WindowRect.GetHeight() };
02264: // TODO consider other DT_* flags
02265: ::DrawText (PaintDC, WindowTextString,
02266: CharCount, & Rect, DT_SINGLELINE /* | DT_CENTER */);
02267:
02268: SetBkMode (PaintDC, PreviousBkMode);
02269: SetTextColor (PaintDC, PreviousForegroundColorRef);
02270: #else
02271:
02272: #ifndef __WXGTK__
02273: // except for wxGTK, support for transparent text-drawing for the
02274: // different ports (wxMOTIF, wxUniversal etc.) in unkown/untested,
02275: // so add a warning here, at least
02276: // sure, above code for wxMSW can't be used in these ports anyway,
02277: // since it uses the Win32 API
02278:
02279: #pragma message ("Please check transparency support of wxStaticText in this wx-port");
02280: #endif
02281: // ???
02282: // for wxGTK, neither wxStaticText nor wxWindow implements a method
02283: // OnPaint we could call, so resort to simply not defining OnPaint()
02284: // in wxGTK (and other ports), thus using the default implementation
02285: // of OnPaint() (see above for message handler definitions)
02286: // wxStaticText::OnPaint (PaintEvent);
02287: // wxWindow::OnPaint (PaintEvent);
02288:
02289: #if wxCHECK_VERSION (2, 5, 3)
02290: wxUnusedVar (PaintEvent);
02291: #endif
02292: #endif
02293: }
02294: #endif // wxUSE_GUI
02295:
02296: //=========================================================================
02297:
02298: #if wxUSE_GUI
02299:
02300: IMPLEMENT_DYNAMIC_CLASS(wxColourBarWindow, wxPanel)
02301:
02302: BEGIN_EVENT_TABLE (wxColourBarWindow, wxPanel)
02303: EVT_ERASE_BACKGROUND (wxColourBarWindow::OnEraseBackground)
02304: EVT_PAINT(wxColourBarWindow::OnPaint)
02305: END_EVENT_TABLE()
02306:
02307: //-------------------------------------------------------------------------
02308:
02309: wxColourBarWindow::wxColourBarWindow ()
02310: {
02311: m_Brush = *wxTRANSPARENT_BRUSH;
02312: m_Pen = *wxTRANSPARENT_PEN;
02313: m_RoundedCornerRadius = 0.;
02314: }
02315:
02316: wxColourBarWindow::wxColourBarWindow (wxWindow * ParentWindow, int ControlIdent,
02317: const wxPoint & Position,
02318: const wxSize & Size,
02319: long Style, const wxString& Name)
02320: : wxPanel (ParentWindow, ControlIdent,
02321: Position, Size,
02322: Style, Name)
02323: {
02324: m_Brush = *wxTRANSPARENT_BRUSH;
02325: m_Pen = *wxTRANSPARENT_PEN;
02326: m_RoundedCornerRadius = 0.;
02327: }
02328:
02329: wxColourBarWindow::wxColourBarWindow (wxWindow * ParentWindow, int ControlIdent,
02330: const wxColour & Colour,
02331: const wxPoint & Position,
02332: const wxSize & Size,
02333: long Style, const wxString& Name)
02334: : wxPanel (ParentWindow, ControlIdent,
02335: Position, Size,
02336: Style, Name)
02337: {
02338: m_Brush.SetColour (Colour);
02339: m_Brush.SetStyle (wxSOLID);
02340: m_RoundedCornerRadius = 0.;
02341: m_Pen = *wxTRANSPARENT_PEN;
02342: }
02343:
02344: //-------------------------------------------------------------------------
02345:
02346: void wxColourBarWindow::setBrush (const wxBrush & Brush)
02347: {
02348: m_Brush = Brush;
02349: }
02350:
02351: void wxColourBarWindow::setRoundedCornerRadius (double RoundedCornerRadius)
02352: {
02353: m_RoundedCornerRadius = RoundedCornerRadius;
02354: }
02355:
02356: void wxColourBarWindow::setPen (const wxPen & Pen)
02357: {
02358: m_Pen = Pen;
02359: }
02360:
02361: //-------------------------------------------------------------------------
02362:
02363: void wxColourBarWindow::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02364: {
02365: // wxPanel::OnEraseBackground (EraseEvent);
02366: }
02367:
02368: void wxColourBarWindow::OnPaint (wxPaintEvent & WXUNUSED(PaintEvent))
02369: {
02370: wxPaintDC PaintWxDC (this);
02371:
02372: wxRect WindowRect = GetClientRect();
02373:
02374: PaintWxDC.SetPen (m_Pen);
02375: PaintWxDC.SetBrush (m_Brush);
02376:
02377: if (m_RoundedCornerRadius == 0.)
02378: {
02379: PaintWxDC.DrawRectangle (WindowRect);
02380: }
02381: else
02382: {
02383: PaintWxDC.DrawRoundedRectangle (WindowRect, m_RoundedCornerRadius);
02384: }
02385: }
02386: #endif // wxUSE_GUI
02387:
02388: //=========================================================================
02389:
02390: #if (M_WxExtLib_IsUseGraphicsHelper == 1)
02391: # if wxUSE_GUI
02392:
02393: IMPLEMENT_DYNAMIC_CLASS(wxScaledImageWindow, wxPanel)
02394:
02395: BEGIN_EVENT_TABLE (wxScaledImageWindow, wxPanel)
02396: EVT_ERASE_BACKGROUND (wxScaledImageWindow::OnEraseBackground)
02397: EVT_PAINT(wxScaledImageWindow::OnPaint)
02398: END_EVENT_TABLE()
02399:
02400: //-------------------------------------------------------------------------
02401:
02402: wxScaledImageWindow::wxScaledImageWindow ()
02403: {
02404: // m_OriginalImage = wxNullImage;
02405: m_IsCacheOkay = false;
02406: }
02407:
02408: wxScaledImageWindow::wxScaledImageWindow (wxWindow * ParentWindow, int ControlIdent,
02409: const wxPoint & Position,
02410: const wxSize & Size,
02411: long Style, const wxString& Name)
02412: : wxPanel (ParentWindow, ControlIdent,
02413: Position, Size,
02414: Style, Name)
02415: {
02416: // m_OriginalImage = wxNullImage;
02417: m_IsCacheOkay = false;
02418: }
02419:
02420: wxScaledImageWindow::wxScaledImageWindow (wxWindow * ParentWindow, int ControlIdent,
02421: const wxImage & Image,
02422: const wxPoint & Position,
02423: const wxSize & Size,
02424: long Style, const wxString& Name)
02425: : wxPanel (ParentWindow, ControlIdent,
02426: Position, Size,
02427: Style, Name)
02428: {
02429: m_OriginalImage = Image;
02430: m_IsCacheOkay = false;
02431: }
02432:
02433: //-------------------------------------------------------------------------
02434:
02435: void wxScaledImageWindow::setImage (const wxImage & Image)
02436: {
02437: m_OriginalImage = Image;
02438: m_IsCacheOkay = false;
02439: }
02440:
02441: //-------------------------------------------------------------------------
02442:
02443: void wxScaledImageWindow::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02444: {
02445: // wxPanel::OnEraseBackground (EraseEvent);
02446: }
02447:
02448: void wxScaledImageWindow::OnPaint (wxPaintEvent & WXUNUSED(PaintEvent))
02449: {
02450: wxPaintDC PaintWxDC (this);
02451:
02452: wxRect WindowRect = GetClientRect();
02453: bool IsOkay = false;
02454:
02455: if ((!m_IsCacheOkay)
02456: || (WindowRect != m_PreviousClientRect))
02457: {
02458: m_PreviousClientRect = WindowRect;
02459: wxImage ScaledImage;
02460: IsOkay = resizeImageVGrid (m_OriginalImage,
02461: ScaledImage,
02462: WindowRect.GetWidth(), WindowRect.GetHeight());
02463:
02464: if (IsOkay)
02465: {
02466: m_ScaledBitmap = wxBitmap (ScaledImage);
02467: m_IsCacheOkay = true;
02468: }
02469: }
02470: else
02471: {
02472: IsOkay = true;
02473: }
02474:
02475: if (IsOkay)
02476: {
02477: PaintWxDC.DrawBitmap (m_ScaledBitmap, 0 /* x */, 0 /* y */, true /* transparent */);
02478: }
02479: else
02480: {
02481: PaintWxDC.SetPen (wxPen (*wxBLACK, 1, wxTRANSPARENT));
02482: PaintWxDC.SetBrush (wxBrush (wxColour (0xA0, 0xA0, 0xF0), wxSOLID));
02483: PaintWxDC.DrawRectangle (WindowRect);
02484: }
02485: }
02486:
02487: # endif // wxUSE_GUI
02488: #endif
02489:
02490: //=========================================================================
02491:
02492: #if wxUSE_GUI
02493: IMPLEMENT_DYNAMIC_CLASS(wxItemWindow, wxWindow)
02494:
02495: BEGIN_EVENT_TABLE (wxItemWindow, wxWindow)
02496: EVT_ERASE_BACKGROUND (wxItemWindow::OnEraseBackground)
02497: EVT_PAINT(wxItemWindow::OnPaint)
02498: END_EVENT_TABLE()
02499:
02500: //-------------------------------------------------------------------------
02501:
02502: wxItemWindow::wxItemWindow ()
02503: {
02504: m_IsSelectable = false;
02505: m_IsFocusable = false;
02506: m_StatusMessageTarget = NULL;
02507:
02508: init ();
02509: }
02510:
02511: wxItemWindow::wxItemWindow (wxWindow * ParentWindow, int ControlIdent,
02512: const wxPoint & Position,
02513: const wxSize & Size,
02514: bool IsSelectable, bool IsFocusable,
02515: wxStatusMessageTarget * StatusMessageTarget,
02516: long Style, const wxString& Name)
02517: : wxWindow (ParentWindow, ControlIdent,
02518: Position, Size,
02519: Style, Name)
02520: {
02521: m_StatusMessageTarget = StatusMessageTarget;
02522: m_IsSelectable = IsSelectable;
02523: m_IsFocusable = IsFocusable;
02524:
02525: init ();
02526: }
02527:
02528: void wxItemWindow::init ()
02529: {
02530: m_IsSelected = false;
02531: m_IsFocused = false;
02532: m_IsBorder = false;
02533: m_IsUsingFocusedBackgroundBrush = false;
02534: }
02535:
02536: //-------------------------------------------------------------------------
02537:
02538: void wxItemWindow::setFocusedBackgroundBrush (const wxBrush & Brush)
02539: {
02540: m_IsUsingFocusedBackgroundBrush = true;
02541: m_FocusedBackgroundBrush = Brush;
02542: }
02543:
02544: //-------------------------------------------------------------------------
02545:
02546: void wxItemWindow::OnEraseBackground (wxEraseEvent & WXUNUSED(EraseEvent))
02547: {
02548: // wxWindow::OnEraseBackground (EraseEvent);
02549: }
02550:
02551: void wxItemWindow::OnPaint (wxPaintEvent & WXUNUSED(PaintEvent))
02552: {
02553: // wxRect WindowRect = GetRect ();
02554: // wxSize ClientSize = GetClientSize();
02555:
02556: wxPaintDC PaintWxDC (this);
02557:
02558: wxRect WindowRect = GetClientRect();
02559:
02560: // NOTE BorderWidth must be <= FocusBorderWidth (if m_IsFocusable)
02561: // or <= SelectionBorderWidth (if m_IsSelectable && !m_IsFocusable)
02562: enum { FocusBorderWidth = 3, SelectionBorderWidth = 3, BorderWidth = 1 };
02563:
02564: // calculate rectangles for borders and item
02565: wxRect ItemRect = WindowRect;
02566: wxRect SelectionIndicationRect = WindowRect;
02567: if (m_IsBorder)
02568: {
02569: if (!m_IsFocusable && !m_IsSelectable)
02570: {
02571: ItemRect.Inflate (-BorderWidth -1, -BorderWidth -1);
02572: SelectionIndicationRect.Inflate (-BorderWidth -1, -BorderWidth -1);
02573: }
02574: }
02575:
02576: if (m_IsFocusable)
02577: {
02578: ItemRect.Inflate (-FocusBorderWidth -1, -FocusBorderWidth -1);
02579: // ItemRect.Offset (FocusBorderWidth, FocusBorderWidth);
02580: SelectionIndicationRect.Inflate (-FocusBorderWidth -1, -FocusBorderWidth -1);
02581: // SelectionIndicationRect.Offset (FocusBorderWidth, FocusBorderWidth);
02582: }
02583:
02584: if (m_IsSelectable)
02585: {
02586: ItemRect.Inflate (-SelectionBorderWidth, -SelectionBorderWidth);
02587: // ItemRect.Offset (SelectionBorderWidth, SelectionBorderWidth);
02588: }
02589:
02590: wxBrush NormalBackgroundBrush = wxBrush (GetBackgroundColour(), wxSOLID);
02591: const wxBrush * BackgroundBrush = NULL;
02592: if (m_IsFocusable
02593: && m_IsFocused
02594: && m_IsUsingFocusedBackgroundBrush)
02595: {
02596: BackgroundBrush = & m_FocusedBackgroundBrush;
02597: }
02598: else
02599: {
02600: BackgroundBrush = & NormalBackgroundBrush;
02601: }
02602:
02603: // draw background "behind" borders and rectangles (if there are any
02604: // rectangles to be drawn)
02605: // NOTE this creates a minimal flicker if rectangles are drawn on the
02606: // rectangle drawn here
02607: if (WindowRect != ItemRect)
02608: {
02609: wxRegion BackgroundRegion (WindowRect);
02610: BackgroundRegion.Subtract (ItemRect);
02611: wxRegionIterator BackgroundRegionIterator (BackgroundRegion);
02612: PaintWxDC.SetBrush (* BackgroundBrush);
02613: PaintWxDC.SetPen (* wxTRANSPARENT_PEN);
02614: while (BackgroundRegionIterator.HaveRects ())
02615: {
02616: PaintWxDC.DrawRectangle (BackgroundRegionIterator.GetRect());
02617: ++BackgroundRegionIterator;
02618: }
02619: }
02620:
02621: // draw borders and rectangles around item
02622: if (m_IsBorder)
02623: {
02624: if ((!m_IsFocusable && !m_IsSelectable)
02625: || (!m_IsFocusable && m_IsSelectable && !m_IsSelected)
02626: || (m_IsFocusable && !m_IsFocused))
02627: {
02628: // draw gray rectangle to indicate area
02629: PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02630: PaintWxDC.SetPen (wxPen (wxColour (0xD0, 0xD0, 0xD0), BorderWidth, wxSOLID));
02631: PaintWxDC.DrawRectangle (WindowRect.GetX(),
02632: WindowRect.GetY(),
02633: WindowRect.GetWidth(),
02634: WindowRect.GetHeight());
02635: }
02636: }
02637:
02638: if (m_IsFocusable)
02639: {
02640: if (m_IsFocused)
02641: {
02642: // draw blue rectangle around image to indicate selection:
02643: // and draw background with a very light gray
02644: // PaintWxDC.SetBrush (wxBrush (wxColour (0xF0, 0xF0, 0xF0), wxSOLID));
02645: if (!m_IsUsingFocusedBackgroundBrush)
02646: {
02647: PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02648: }
02649: else
02650: {
02651: PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02652: // PaintWxDC.SetBrush (m_FocusedBackgroundBrush);
02653: }
02654: PaintWxDC.SetPen (wxPen (wxColour (192, 32, 32), FocusBorderWidth, wxSOLID));
02655: PaintWxDC.DrawRectangle (WindowRect.GetX(),
02656: WindowRect.GetY(),
02657: WindowRect.GetWidth(),
02658: WindowRect.GetHeight());
02659: }
02660: }
02661:
02662: if (m_IsSelectable)
02663: {
02664: if (m_IsSelected)
02665: {
02666: // draw blue rectangle around image to indicate selection:
02667: PaintWxDC.SetBrush (* wxTRANSPARENT_BRUSH);
02668: PaintWxDC.SetPen (wxPen (wxColour (32, 0, 160), SelectionBorderWidth, wxSOLID));
02669: PaintWxDC.DrawRectangle (SelectionIndicationRect.GetX(),
02670: SelectionIndicationRect.GetY(),
02671: SelectionIndicationRect.GetWidth(),
02672: SelectionIndicationRect.GetHeight());
02673: }
02674: }
02675:
02676: // draw item
02677: handleItemPaint (PaintWxDC, ItemRect, BackgroundBrush);
02678: }
02679:
02680: void wxItemWindow::handleItemPaint (wxPaintDC & PaintWxDC,
02681: const wxRect & ItemRect,
02682: const wxBrush * BackgroundBrush)
02683: {
02684: PaintWxDC.SetBrush (* BackgroundBrush);
02685: PaintWxDC.SetPen (* wxTRANSPARENT_PEN);
02686: PaintWxDC.DrawRectangle (ItemRect);
02687: }
02688: #endif // wxUSE_GUI
02689:
02690: //=========================================================================
02691:
02692: #if defined(__WXMSW__)
02693:
02694: #if wxUSE_GUI
02695: void drawDIBFitted (wxDC & WxDC, int X, int Y, int Width, int Height,
02696: WXHDIB DIBHandle,
02697: const wxBrush * BackgroundBrush)
02698: {
02699: for_once
02700: {
02701: if (DIBHandle == NULL)
02702: break;
02703:
02704: // get DIB width and height:
02705: BITMAPINFO * BitmapInfo = (LPBITMAPINFO) GlobalLock (DIBHandle);
02706: if (BitmapInfo == NULL)
02707: break;
02708:
02709: BITMAPINFOHEADER * BitmapInfoHeader = (LPBITMAPINFOHEADER) BitmapInfo;
02710:
02711: int ImageWidth = BitmapInfoHeader -> biWidth;
02712: int ImageHeight = BitmapInfoHeader -> biHeight;
02713: int ColorPaletteSize = getActualUsedColorCount (BitmapInfo) * sizeof (RGBQUAD);
02714:
02715: unsigned char * BitmapData = ((unsigned char *) BitmapInfo)
02716: + BitmapInfoHeader -> biSize
02717: + ColorPaletteSize;
02718:
02719: wxRect Rect (X, Y, Width, Height);
02720: wxSize Size (ImageWidth, ImageHeight);
02721: wxRect FittedRect;
02722: fitInside (Rect, Size, FittedRect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
02723:
02724: FittedRect.Inflate (-1);
02725:
02726: // draw background around image if desired
02727: if (BackgroundBrush != NULL)
02728: {
02729: wxRegion BackgroundRegion (X, Y, Width, Height);
02730: BackgroundRegion.Subtract (FittedRect);
02731: wxRegionIterator BackgroundRegionIterator (BackgroundRegion);
02732: while (BackgroundRegionIterator.HaveRects ())
02733: {
02734: WxDC.SetBrush (* BackgroundBrush);
02735: WxDC.SetPen (* wxTRANSPARENT_PEN);
02736: WxDC.DrawRectangle (BackgroundRegionIterator.GetRect());
02737: ++BackgroundRegionIterator;
02738: }
02739: }
02740:
02741: // draw DIB
02742: HDC DCHandle = (HDC) WxDC.GetHDC();
02743: ::SetStretchBltMode (DCHandle, COLORONCOLOR);
02744: ::StretchDIBits (DCHandle,
02745: FittedRect.GetX(), FittedRect.GetY(),
02746: FittedRect.GetWidth(), FittedRect.GetHeight(),
02747: 0, 0, ImageWidth, ImageHeight,
02748: (void *) BitmapData,
02749: BitmapInfo,
02750: DIB_RGB_COLORS, SRCCOPY);
02751:
02752: FittedRect.Inflate (1);
02753:
02754: WxDC.SetBrush (*wxTRANSPARENT_BRUSH);
02755: WxDC.SetPen (*wxBLACK_PEN);
02756: WxDC.DrawRectangle (FittedRect.GetX(), FittedRect.GetY(),
02757: FittedRect.GetWidth(), FittedRect.GetHeight());
02758:
02759: GlobalUnlock (DIBHandle);
02760: }
02761: }
02762: #endif // wxUSE_GUI
02763:
02764: #endif
02765:
02766: //=========================================================================
02767:
02768: #if defined(__WXMSW__)
02769:
02770: #if wxUSE_GUI
02771: wxImageProxy::wxImageProxy ()
02772: {
02773: m_DIBFromFile = NULL;
02774: }
02775:
02776: wxImageProxy::~wxImageProxy ()
02777: {
02778: freeDIB ();
02779: }
02780:
02781: void wxImageProxy::freeDIB ()
02782: {
02783: if (m_DIBFromFile != NULL)
02784: {
02785: GlobalFree (m_DIBFromFile);
02786: m_DIBFromFile = NULL;
02787: }
02788: }
02789:
02790: void wxImageProxy::discard ()
02791: {
02792: freeDIB ();
02793: }
02794:
02795: void wxImageProxy::draw (wxDC & PaintWxDC, int X, int Y, int Width, int Height,
02796: EResolutionIdent ResolutionIdent,
02797: const wxBrush * BackgroundBrush)
02798: {
02799: for_once
02800: {
02801: WXHDIB DIBHandle = NULL;
02802: getDIB (ResolutionIdent, DIBHandle);
02803: if (DIBHandle == NULL)
02804: break;
02805:
02806: drawDIBFitted (PaintWxDC, X, Y, Width, Height,
02807: DIBHandle,
02808: BackgroundBrush);
02809: }
02810: }
02811: #endif // wxUSE_GUI
02812:
02813: #endif // defined(__WXMSW__)
02814:
02815: //=========================================================================
02816:
02817: #if defined(__WXMSW__)
02818:
02819: #if wxUSE_GUI
02820: wxBitmapPaintHelper::wxBitmapPaintHelper (const wxString & ResourceIdentString)
02821: {
02822: loadBitmap (ResourceIdentString);
02823: };
02824:
02825: wxBitmapPaintHelper::wxBitmapPaintHelper (const wxString & ResourceIdentString, HDC PaintDCHandle)
02826: {
02827: loadBitmap (ResourceIdentString);
02828: prepare (PaintDCHandle);
02829: };
02830:
02831: wxBitmapPaintHelper::wxBitmapPaintHelper (wxBitmap & Bitmap)
02832: {
02833: setBitmap (Bitmap);
02834: };
02835:
02836: wxBitmapPaintHelper::wxBitmapPaintHelper (wxBitmap & Bitmap, HDC PaintDCHandle)
02837: {
02838: setBitmap (Bitmap);
02839: prepare (PaintDCHandle);
02840: };
02841:
02842: wxBitmapPaintHelper::wxBitmapPaintHelper (int Width, int Height)
02843: {
02844: createBitmap (Width, Height);
02845: };
02846:
02847: wxBitmapPaintHelper::wxBitmapPaintHelper (int Width, int Height, HDC PaintDCHandle)
02848: {
02849: createBitmap (Width, Height);
02850: prepare (PaintDCHandle);
02851: };
02852:
02853: wxBitmapPaintHelper::~wxBitmapPaintHelper ()
02854: {
02855: release ();
02856: };
02857:
02858: void wxBitmapPaintHelper::setBitmap (wxBitmap & Bitmap)
02859: {
02860: m_BitmapRef = & Bitmap;
02861: m_BitmapHandle = (HBITMAP) m_BitmapRef -> GetHBITMAP ();
02862: }
02863:
02864: void wxBitmapPaintHelper::loadBitmap (const wxString & ResourceIdentString)
02865: {
02866: // m_BitmapHandle = ::LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE(ResourceIdent));
02867: m_Bitmap.LoadFile (ResourceIdentString, wxBITMAP_TYPE_BMP_RESOURCE);
02868: m_BitmapRef = & m_Bitmap;
02869: m_BitmapHandle = (HBITMAP) m_BitmapRef -> GetHBITMAP ();
02870: }
02871:
02872: void wxBitmapPaintHelper::createBitmap (int Width, int Height)
02873: {
02874: m_Bitmap.Create (Width, Height);
02875: m_BitmapRef = & m_Bitmap;
02876: m_BitmapHandle = (HBITMAP) m_BitmapRef -> GetHBITMAP ();
02877: }
02878:
02879: void wxBitmapPaintHelper::prepare (HDC PaintDCHandle)
02880: {
02881: m_MemoryDCHandle = ::CreateCompatibleDC (PaintDCHandle);
02882: m_PreviousBitmapHandle = (HBITMAP) ::SelectObject (m_MemoryDCHandle, m_BitmapHandle);
02883: }
02884:
02885: void wxBitmapPaintHelper::release ()
02886: {
02887: ::SelectObject (m_MemoryDCHandle, m_PreviousBitmapHandle);
02888: ::DeleteDC (m_MemoryDCHandle);
02889: }
02890:
02891: int wxBitmapPaintHelper::getWidth ()
02892: {
02893: return m_BitmapRef -> GetWidth ();
02894: }
02895:
02896: int wxBitmapPaintHelper::getHeight ()
02897: {
02898: return m_BitmapRef -> GetHeight ();
02899: }
02900: #endif // wxUSE_GUI
02901:
02902: #endif // defined(__WXMSW__)
02903:
02904: //=========================================================================
02905:
02906: #if defined(__WXMSW__)
02907:
02908: #if wxUSE_GUI
02909: int getActualUsedColorCount (BITMAPINFO * BitmapInfo)
02910: {
02911: int ColorsUsed = BitmapInfo -> bmiHeader.biClrUsed;
02912: // (for BI_RGB):
02913: // biClrUsed == 0 is interpreted differently depending on the
02914: // bit depth used:
02915: // - for color depths from 1..8 bpp: if biClrUsed is set to zero
02916: // this means that a palette for all possible colors is there
02917: // - for color depths 16, 24 or 32 bpp: if biClrUsed is set to
02918: // zero this means that no palette is used (but biClrUsed
02919: // may be set to non-zero if a palette is there for
02920: // output optimization purposes)
02921: if (ColorsUsed == 0
02922: && BitmapInfo -> bmiHeader.biBitCount >= 1
02923: && BitmapInfo -> bmiHeader.biBitCount <= 8) // FUZZY 8
02924: ColorsUsed = (1 << BitmapInfo -> bmiHeader.biBitCount);
02925:
02926: return ColorsUsed;
02927: }
02928: #endif // wxUSE_GUI
02929:
02930: #endif // defined(__WXMSW__)
02931:
02932: //=========================================================================
02933:
02934: void WxBeep (int MilliSeconds)
02935: {
02936: wxMinimalTimeInterval MinimalTimeInterval;
02937: MinimalTimeInterval.setMinimalTimeInterval (MilliSeconds);
02938:
02939: while (!MinimalTimeInterval.check ())
02940: {
02941: wxBell ();
02942: }
02943: }
02944:
02945: //=========================================================================
02946:
02947: void doRotateMirrorCoord (int RotationAngle,
02948: bool IsHorizontallyMirrored,
02949: bool IsVerticallyMirrored,
02950: const wxPoint & CentrePoint,
02951: const wxPoint & InputPoint,
02952: wxPoint & OutputPoint,
02953: bool IsRotateCenter)
02954: {
02955: wxPoint DistanceAsPoint = InputPoint - CentrePoint;
02956:
02957: wxPoint RotatedDistanceAsPoint = DistanceAsPoint;
02958: switch (RotationAngle)
02959: {
02960: case 90:
02961: RotatedDistanceAsPoint.x = DistanceAsPoint.y;
02962: RotatedDistanceAsPoint.y = -DistanceAsPoint.x;
02963: break;
02964: case 180:
02965: RotatedDistanceAsPoint.x = -DistanceAsPoint.x;
02966: RotatedDistanceAsPoint.y = -DistanceAsPoint.y;
02967: break;
02968: case 270:
02969: RotatedDistanceAsPoint.x = -DistanceAsPoint.y;
02970: RotatedDistanceAsPoint.y = DistanceAsPoint.x;
02971: break;
02972: }
02973:
02974: // PERFORMANCE NOTE doing the negation is possibly faster than
02975: // multiplicating with (-1)
02976: wxPoint MirroredDistanceAsPoint = RotatedDistanceAsPoint;
02977: if (IsHorizontallyMirrored)
02978: {
02979: MirroredDistanceAsPoint.x = -RotatedDistanceAsPoint.x;
02980: }
02981: if (IsVerticallyMirrored)
02982: {
02983: MirroredDistanceAsPoint.y = -RotatedDistanceAsPoint.y;
02984: }
02985:
02986: wxPoint NewCentrePoint;
02987: if (IsRotateCenter
02988: && (RotationAngle == 90 || RotationAngle == 270))
02989: {
02990: NewCentrePoint.x = CentrePoint.y;
02991: NewCentrePoint.y = CentrePoint.x;
02992: }
02993: else
02994: {
02995: NewCentrePoint.x = CentrePoint.x;
02996: NewCentrePoint.y = CentrePoint.y;
02997: }
02998: OutputPoint = NewCentrePoint + MirroredDistanceAsPoint;
02999: }
03000:
03001: //=========================================================================
03002:
03003: wxRotationMirrorState::wxRotationMirrorState()
03004: {
03005: m_IsHorizontallyMirrored = false;
03006: m_IsVerticallyMirrored = false;
03007: m_RotationAngle = 0;
03008:
03009: m_IsUpdateRequired = true;
03010: }
03011:
03012: wxRotationMirrorState::~wxRotationMirrorState()
03013: {
03014: }
03015:
03016: void wxRotationMirrorState::reset()
03017: {
03018: m_IsHorizontallyMirrored = false;
03019: m_IsVerticallyMirrored = false;
03020: m_RotationAngle = 0;
03021:
03022: m_IsUpdateRequired = true;
03023: }
03024:
03025: //-------------------------------------------------------------------------
03026:
03027: void wxRotationMirrorState::mirror (bool IsHorizontallyMirrored, bool IsVerticallyMirrored)
03028: {
03029: // handleMirrorRotation (m_RotationAngle,
03030: // IsHorizontallyMirrored,
03031: // IsVerticallyMirrored);
03032:
03033: if (IsHorizontallyMirrored)
03034: {
03035: m_IsHorizontallyMirrored = !m_IsHorizontallyMirrored;
03036: }
03037: if (IsVerticallyMirrored)
03038: {
03039: m_IsVerticallyMirrored = !m_IsVerticallyMirrored;
03040: }
03041:
03042: m_IsUpdateRequired = true;
03043: }
03044:
03045: void wxRotationMirrorState::rotate (int RotationAngle)
03046: {
03047: m_RotationAngle += RotationAngle;
03048: m_RotationAngle = (((int) m_RotationAngle) / 90) * 90;
03049: if (m_RotationAngle < 0)
03050: m_RotationAngle += 360;
03051: m_RotationAngle %= 360;
03052:
03053: handleMirrorRotation (RotationAngle,
03054: m_IsHorizontallyMirrored,
03055: m_IsVerticallyMirrored);
03056:
03057: m_IsUpdateRequired = true;
03058: }
03059:
03060: void wxRotationMirrorState::handleMirrorRotation(int RotationAngle,
03061: bool & IsHorizontallyMirrored,
03062: bool & IsVerticallyMirrored)
03063: {
03064: if (RotationAngle < 0)
03065: RotationAngle += 360;
03066: RotationAngle %= 360;
03067: if (RotationAngle == 90
03068: || RotationAngle == 270)
03069: {
03070: if ((IsHorizontallyMirrored && !IsVerticallyMirrored)
03071: || (!IsHorizontallyMirrored && IsVerticallyMirrored))
03072: {
03073: // swap mirroring axes
03074: bool TempVerticallyMirrored = IsVerticallyMirrored;
03075: IsVerticallyMirrored = IsHorizontallyMirrored;
03076: IsHorizontallyMirrored = TempVerticallyMirrored;
03077: }
03078: }
03079: }
03080:
03081: void wxRotationMirrorState::getNormalizedState(int & RotationAngle,
03082: bool & IsHorizontallyMirrored,
03083: bool & IsVerticallyMirrored)
03084: {
03085: IsHorizontallyMirrored = m_IsHorizontallyMirrored;
03086: IsVerticallyMirrored = m_IsVerticallyMirrored;
03087: RotationAngle = m_RotationAngle;
03088:
03089: // normalize to reduce number of required image transformations:
03090: if (IsHorizontallyMirrored
03091: && IsVerticallyMirrored)
03092: {
03093: RotationAngle += 180;
03094: RotationAngle %= 360;
03095: IsHorizontallyMirrored = false;
03096: IsVerticallyMirrored = false;
03097: }
03098: }
03099:
03100: //-------------------------------------------------------------------------
03101:
03102: void wxRotationMirrorState::assign (const wxRotationMirrorState & RHSRotationMirrorState)
03103: {
03104: m_RotationAngle = RHSRotationMirrorState.m_RotationAngle;
03105: m_IsHorizontallyMirrored = RHSRotationMirrorState.m_IsHorizontallyMirrored;
03106: m_IsVerticallyMirrored = RHSRotationMirrorState.m_IsVerticallyMirrored;
03107:
03108: m_IsUpdateRequired = true;
03109: }
03110:
03111: void wxRotationMirrorState::subtract (const wxRotationMirrorState & LHSRotationMirrorState,
03112: const wxRotationMirrorState & RHSRotationMirrorState)
03113: {
03114: reset();
03115:
03116: int RotationAngleDifference = LHSRotationMirrorState.m_RotationAngle
03117: - RHSRotationMirrorState.m_RotationAngle;
03118:
03119: wxRotationMirrorState LHS;
03120: wxRotationMirrorState RHS;
03121: LHS.assign (LHSRotationMirrorState);
03122: RHS.assign (RHSRotationMirrorState);
03123:
03124: // rotate LHS to rotation angle of RHS, then determine differences in
03125: // mirroring, then apply mirroring and finally rotate
03126: LHS.rotate (- RotationAngleDifference);
03127: m_IsHorizontallyMirrored = RHS.m_IsHorizontallyMirrored != LHS.m_IsHorizontallyMirrored;
03128: m_IsVerticallyMirrored = RHS.m_IsVerticallyMirrored != LHS.m_IsVerticallyMirrored;
03129: rotate (RotationAngleDifference);
03130:
03131: m_IsUpdateRequired = true;
03132: }
03133:
03134: //=========================================================================
03135:
03136: #ifdef M_WxExtLib_IsFilteredDIBEnabled
03137:
03138: #if defined(__WXMSW__)
03139:
03140: #if wxUSE_GUI
03141: wxFilteredDIB::wxFilteredDIB ()
03142: {
03143: m_Brightness = 0.;
03144: m_Contrast = 0.;
03145: m_RedGamma = 1.;
03146: m_GreenGamma = 1.;
03147: m_BlueGamma = 1.;
03148: m_IsInverted = false;
03149: m_IsColorAdjustmentModified = true;
03150:
03151: // m_IsPaletteBasedColorAdjustmentEnabled = true;
03152: m_IsOriginalColorPaletteRemembered = false;
03153: m_IsModifiedColorPaletteRemembered = false;
03154:
03155: m_IsImageMagickFilteringRequired = false;
03156: m_IsFilteringModified = true;
03157:
03158: m_PreviousRotationMirrorState.reset ();
03159: m_RotationMirrorState.reset();
03160: m_RotationMirrorState.m_IsUpdateRequired = true;
03161:
03162: m_SourceDIBHandle = NULL;
03163: m_IsOwningSourceImage = false;
03164: m_ResultDIBHandle = NULL;
03165: m_IsOwningResultImage = true;
03166:
03167: m_FilteredDIBBitsPerPixel = 24;
03168: }
03169:
03170: wxFilteredDIB::~wxFilteredDIB ()
03171: {
03172: freeResultImage ();
03173: freeSourceImage ();
03174: }
03175:
03176: //-------------------------------------------------------------------------
03177:
03178: void wxFilteredDIB::setBrightnessContrast (double Brightness, double Contrast)
03179: {
03180: m_Brightness = Brightness;
03181: m_Contrast = Contrast;
03182: m_IsColorAdjustmentModified = true;
03183: }
03184:
03185: void wxFilteredDIB::setColorAdjustment (double RedGamma, double GreenGamma,
03186: double BlueGamma)
03187: {
03188: m_RedGamma = RedGamma;
03189: m_GreenGamma = GreenGamma;
03190: m_BlueGamma = BlueGamma;
03191: m_IsColorAdjustmentModified = true;
03192: }
03193:
03194: void wxFilteredDIB::setInversion (bool IsInverted)
03195: {
03196: m_IsInverted = IsInverted;
03197: m_IsColorAdjustmentModified = true;
03198: }
03199:
03200: //-------------------------------------------------------------------------
03201:
03202: bool wxFilteredDIB::rememberPalette (WXHDIB DIBHandle,
03203: wxFilteredDIBColorPaletteArray & ColorPaletteByteArray)
03204: {
03205: int DIBColorPaletteEntryCount = ::GetActualUsedColorCountInDIBHandle (DIBHandle);
03206:
03207: ColorPaletteByteArray.Clear ();
03208:
03209: if (DIBColorPaletteEntryCount == 0)
03210: return false;
03211:
03212: ColorPaletteByteArray.Insert ((BYTE) 0, /* array index */ 0,
03213: DIBColorPaletteEntryCount);
03214:
03215: // HACK WARN access of items in m_OriginalColorPaletteByteArray
03216: ::ImportExportColorPaletteIntoDIB ((BYTE *) (& ColorPaletteByteArray.Item(0)),
03217: DIBColorPaletteEntryCount,
03218: DIBHandle,
03219: false);
03220:
03221: return true;
03222: }
03223:
03224: bool wxFilteredDIB::restorePalette (WXHDIB DIBHandle,
03225: wxFilteredDIBColorPaletteArray & ColorPaletteByteArray)
03226: {
03227: int ColorPaletteEntryCount = ColorPaletteByteArray.GetCount();
03228:
03229: if (ColorPaletteEntryCount != 0)
03230: {
03231: // HACK WARN access of items in m_OriginalColorPaletteByteArray
03232: ::ImportExportColorPaletteIntoDIB ((BYTE *) (& ColorPaletteByteArray.Item(0)),
03233: ColorPaletteEntryCount,
03234: DIBHandle,
03235: true);
03236: }
03237:
03238: return true;
03239: }
03240:
03241: void wxFilteredDIB::rememberOriginalPalette ()
03242: {
03243: rememberPalette (m_SourceDIBHandle,
03244: m_OriginalColorPaletteByteArray);
03245: m_IsOriginalColorPaletteRemembered = true;
03246: }
03247:
03248: void wxFilteredDIB::rememberModifiedPalette ()
03249: {
03250: rememberPalette (m_SourceDIBHandle,
03251: m_ModifiedColorPaletteByteArray);
03252: m_IsModifiedColorPaletteRemembered = true;
03253: }
03254:
03255: void wxFilteredDIB::setOriginalPaletteIntoSourceImage ()
03256: {
03257: if (m_IsOriginalColorPaletteRemembered)
03258: {
03259: restorePalette (m_SourceDIBHandle,
03260: m_OriginalColorPaletteByteArray);
03261: }
03262: }
03263:
03264: void wxFilteredDIB::setModifiedPaletteIntoSourceImage ()
03265: {
03266: if (m_IsModifiedColorPaletteRemembered)
03267: {
03268: restorePalette (m_SourceDIBHandle,
03269: m_ModifiedColorPaletteByteArray);
03270: }
03271: }
03272:
03273: bool wxFilteredDIB::getIsUsePaletteAlienation ()
03274: {
03275: return false;
03276: }
03277:
03278: bool wxFilteredDIB::applyPaletteAlienation (wxFilteredDIBColorPaletteArray & ColorPaletteByteArray)
03279: {
03280: return false;
03281: }
03282:
03283: //-------------------------------------------------------------------------
03284:
03285: void wxFilteredDIB::resetRotationMirror ()
03286: {
03287: m_RotationMirrorState.reset();
03288: }
03289:
03290: void wxFilteredDIB::rotate (int RotationAngle)
03291: {
03292: m_RotationMirrorState.rotate (RotationAngle);
03293: }
03294:
03295: void wxFilteredDIB::mirror (bool IsHorizontallyMirrored, bool IsVerticallyMirrored)
03296: {
03297: m_RotationMirrorState.mirror (IsHorizontallyMirrored, IsVerticallyMirrored);
03298: }
03299:
03300: //-------------------------------------------------------------------------
03301:
03302: void wxFilteredDIB::setIsFilteringModified ()
03303: {
03304: m_IsFilteringModified = true;
03305: }
03306:
03307: void wxFilteredDIB::setIsImageMagickFilteringRequired (bool IsRequired)
03308: {
03309: m_IsImageMagickFilteringRequired = IsRequired;
03310: m_IsFilteringModified = true;
03311: }
03312:
03313: //-------------------------------------------------------------------------
03314:
03315: void wxFilteredDIB::setSourceImage (const WXHDIB & SourceDIBHandle)
03316: {
03317: m_SourceDIBHandle = SourceDIBHandle;
03318: m_IsColorAdjustmentModified = true;
03319: m_IsFilteringModified = true;
03320: }
03321:
03322: void wxFilteredDIB::getResultImage (WXHDIB & ResultDIBHandle)
03323: {
03324: if (m_ResultDIBHandle == NULL)
03325: ResultDIBHandle = m_SourceDIBHandle;
03326: else
03327: ResultDIBHandle = m_ResultDIBHandle;
03328: }
03329:
03330: void wxFilteredDIB::setIsOwningSourceImage (bool IsOwningSourceImage)
03331: {
03332: m_IsOwningSourceImage = IsOwningSourceImage;
03333: }
03334:
03335: void wxFilteredDIB::setIsOwningResultImage (bool IsOwningResultImage)
03336: {
03337: m_IsOwningResultImage = IsOwningResultImage;
03338: }
03339:
03340: //-------------------------------------------------------------------------
03341:
03342: void wxFilteredDIB::updateResultImage()
03343: {
03344: if (! (m_IsColorAdjustmentModified
03345: || m_IsFilteringModified
03346: || m_RotationMirrorState.m_IsUpdateRequired))
03347: return;
03348:
03349: // rotation mirror optmization: avoid applying color adjustment and filtering
03350: // if only rotation or mirroring has changed - this assumes that rotation
03351: // and mirroring doesn't change image contents (apart from rotation and
03352: // mirroring)
03353: bool IsRotationMirrorOnly = m_RotationMirrorState.m_IsUpdateRequired
03354: && ! m_IsColorAdjustmentModified
03355: && ! m_IsFilteringModified;
03356:
03357: for_once
03358: {
03359: if (!IsRotationMirrorOnly)
03360: freeResultImage ();
03361:
03362: // obtain original DIB
03363: if (m_SourceDIBHandle == NULL)
03364: break;
03365:
03366: //-------------------------------------------------------------------------
03367: // try to apply color adjustment to palette DIBs
03368:
03369: bool IsPaletteBasedColorAdjustmentDone = false;
03370:
03371: if (m_IsPaletteBasedColorAdjustmentEnabled
03372: && (! IsRotationMirrorOnly))
03373: {
03374: // do palette modification using an ImageMagick filter - to this end,
03375: // convert to 'image', then run filtering, then write result back
03376: // into the DIB palette
03377: ExceptionInfo exceptionInfo;
03378: GetExceptionInfo (& exceptionInfo);
03379:
03380: Image * PaletteMagickImage = NULL;
03381:
03382: if (!m_IsOriginalColorPaletteRemembered)
03383: {
03384: rememberOriginalPalette ();
03385: }
03386: else
03387: {
03388: setOriginalPaletteIntoSourceImage ();
03389: }
03390:
03391: // WARN DIBColorPaletteEntryCount may be only palette for optimization
03392: // purposes, which would have to be ignored
03393: int DIBColorPaletteEntryCount = ::GetActualUsedColorCountInDIBHandle (m_SourceDIBHandle);
03394: bool IsPaletteImage = DIBColorPaletteEntryCount > 0;
03395: if (IsPaletteImage)
03396: {
03397: // use m_ModifiedColorPaletteByteArray as temporary buffer
03398: // to apply palette alienation and modification
03399: rememberPalette (m_SourceDIBHandle, m_ModifiedColorPaletteByteArray);
03400:
03401: if (IsPaletteImage
03402: && getIsUsePaletteAlienation())
03403: {
03404: applyPaletteAlienation (m_ModifiedColorPaletteByteArray);
03405: }
03406:
03407: const char * MapString = "BGRA"; // or maybe RGBO
03408: RGBQUAD * PaletteRGBAArray = (RGBQUAD *) & (m_ModifiedColorPaletteByteArray[0]);
03409: // transfer color values from palette to ImageMagick Image:
03410: // the whole palette is put into a single row with DIBColorPaletteEntryCount
03411: // "pixels"
03412: PaletteMagickImage = ConstituteImage (DIBColorPaletteEntryCount,
03413: /* Height */ 1,
03414: MapString,
03415: CharPixel,
03416: PaletteRGBAArray,
03417: & exceptionInfo);
03418: //
03419: // bool IsPaletteImage = ::DIBPaletteToImage (m_SourceDIBHandle,
03420: // & PaletteMagickImage,
03421: // & exceptionInfo);
03422:
03423: if (PaletteMagickImage == NULL)
03424: break;
03425:
03426: // note that applyColorAdjustment() is an in-place operation
03427: applyColorAdjustment (& PaletteMagickImage, & exceptionInfo);
03428: if (PaletteMagickImage == NULL)
03429: break;
03430:
03431: bool IsOk = ::ImageToDIBPalette (PaletteMagickImage,
03432: m_SourceDIBHandle,
03433: & exceptionInfo);
03434: ::DestroyImage (PaletteMagickImage);
03435: PaletteMagickImage = NULL;
03436:
03437: // WARN should add exception/error handling/parsing after
03438: // each function
03439:
03440: if (IsOk == false)
03441: break;
03442:
03443: IsPaletteBasedColorAdjustmentDone = true;
03444:
03445: rememberModifiedPalette ();
03446: }
03447: }
03448:
03449: WXHDIB IntermediateDIBHandle = m_SourceDIBHandle;
03450: WXHDIB PreviousIntermediateDIBHandle = m_SourceDIBHandle;
03451:
03452: //-------------------------------------------------------------------------
03453: // convert to ImageMagick image and apply color adjustment and ImageMagick filters
03454:
03455: if ((m_IsImageMagickFilteringRequired
03456: || !IsPaletteBasedColorAdjustmentDone)
03457: && (!IsRotationMirrorOnly))
03458: {
03459: // do ImageMagick filtering - to this end, convert to 'image'
03460: // then run filtering, then convert back to DIB
03461: ExceptionInfo exceptionInfo;
03462: GetExceptionInfo (& exceptionInfo);
03463:
03464: Image * MagickImage = ::DIBToImage (PreviousIntermediateDIBHandle,
03465: & exceptionInfo);
03466: if (MagickImage == NULL)
03467: break;
03468:
03469: // check not to do color adjustment twice
03470: if (! IsPaletteBasedColorAdjustmentDone)
03471: {
03472: applyColorAdjustment (& MagickImage, & exceptionInfo);
03473: }
03474:
03475: applyImageMagickFiltering (& MagickImage, & exceptionInfo);
03476: if (MagickImage == NULL)
03477: break;
03478:
03479: IntermediateDIBHandle = ::ImageToDIB (MagickImage,
03480: m_FilteredDIBBitsPerPixel,
03481: & exceptionInfo);
03482: ::DestroyImage (MagickImage);
03483: MagickImage = NULL;
03484: if (IntermediateDIBHandle == NULL)
03485: break;
03486:
03487: // WARN should add exception/error handling/parsing after
03488: // each function
03489: // throwException (exceptionInfo);
03490: // if (image)
03491: // throwException (image->exception);
03492: }
03493:
03494: // clean up of temporary DIB's
03495: if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03496: && PreviousIntermediateDIBHandle != m_SourceDIBHandle)
03497: {
03498: freeImage (PreviousIntermediateDIBHandle);
03499: }
03500: PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03501:
03502: //-------------------------------------------------------------------------
03503: // rotate and mirror:
03504:
03505: int RotationAngle;
03506: bool IsHorizontallyMirrored;
03507: bool IsVerticallyMirrored;
03508: if (IsRotationMirrorOnly)
03509: {
03510: wxRotationMirrorState RelativeRotationMirrorState;
03511:
03512: RelativeRotationMirrorState.subtract (m_RotationMirrorState,
03513: m_PreviousRotationMirrorState);
03514:
03515: RelativeRotationMirrorState.getNormalizedState (RotationAngle,
03516: IsHorizontallyMirrored,
03517: IsVerticallyMirrored);
03518:
03519: // setup DIB handle for input to rotation function
03520: if (m_ResultDIBHandle != NULL)
03521: {
03522: // if NULL, PreviousIntermediateDIBHandle should be set to
03523: // m_SourceDIBHandle
03524: PreviousIntermediateDIBHandle = m_ResultDIBHandle;
03525: }
03526: }
03527: else
03528: {
03529: m_RotationMirrorState.getNormalizedState (RotationAngle,
03530: IsHorizontallyMirrored,
03531: IsVerticallyMirrored);
03532: }
03533:
03534: if (RotationAngle != 0
03535: || IsHorizontallyMirrored
03536: || IsVerticallyMirrored)
03537: {
03538: bool IsNewRotatedDIBHandle = false;
03539: applyImageRotationMirroring (RotationAngle,
03540: IsHorizontallyMirrored,
03541: IsVerticallyMirrored,
03542: PreviousIntermediateDIBHandle,
03543: IntermediateDIBHandle,
03544: IsNewRotatedDIBHandle);
03545:
03546: // release temporary memory
03547: // if (IsNewFilteredDIBHandle)
03548: // freeImage (FilteredDIBHandle);
03549: if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03550: && PreviousIntermediateDIBHandle != m_SourceDIBHandle)
03551: {
03552: freeImage (PreviousIntermediateDIBHandle);
03553: }
03554: PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03555: }
03556:
03557: if (PreviousIntermediateDIBHandle != m_SourceDIBHandle)
03558: {
03559: m_ResultDIBHandle = PreviousIntermediateDIBHandle;
03560: }
03561: else
03562: {
03563: m_ResultDIBHandle = NULL;
03564: }
03565:
03566: m_IsColorAdjustmentModified = false;
03567: m_IsFilteringModified = false;
03568: m_RotationMirrorState.m_IsUpdateRequired = false;
03569: m_PreviousRotationMirrorState.assign (m_RotationMirrorState);
03570:
03571: handleResultImageChanged ();
03572: }
03573: }
03574:
03575: //-------------------------------------------------------------------------
03576:
03577: void wxFilteredDIB::handleResultImageChanged ()
03578: {
03579: }
03580:
03581: //-------------------------------------------------------------------------
03582:
03583: void wxFilteredDIB::applyColorAdjustment (struct _Image ** MagickImagePtrPtr,
03584: struct _ExceptionInfo * exceptionInfo)
03585: {
03586: for_once
03587: {
03588: Image * MagickImage = *MagickImagePtrPtr;
03589: if (MagickImage == NULL)
03590: break;
03591:
03592: if (m_IsInverted)
03593: NegateImage (MagickImage, 0);
03594:
03595: // WARN ContrastImage() seems to use only the sign of
03596: // the 'sharpen' parameter
03597: ContrastImage (MagickImage, (m_Contrast * 100));
03598:
03599: // support for brightness currently done by modifying the gamma
03600: // of each channel
03601: double RedGamma = m_Brightness + m_RedGamma;
03602: double GreenGamma = m_Brightness + m_GreenGamma;
03603: double BlueGamma = m_Brightness + m_BlueGamma;
03604:
03605: levelGamma (RedGamma);
03606: levelGamma (GreenGamma);
03607: levelGamma (BlueGamma);
03608:
03609: GammaImageChannel (MagickImage, RedChannel, RedGamma);
03610: GammaImageChannel (MagickImage, GreenChannel, GreenGamma);
03611: GammaImageChannel (MagickImage, BlueChannel, BlueGamma);
03612: }
03613: }
03614:
03615: void wxFilteredDIB::levelGamma (double & Gamma)
03616: {
03617: if (Gamma < 1.)
03618: {
03619: Gamma = 1. - (1. - Gamma) * 0.75;
03620: }
03621: else if (Gamma > 1.)
03622: {
03623: Gamma = 1. + (Gamma - 1.) * 1.75;
03624: }
03625: if (Gamma < 0.1)
03626: {
03627: Gamma = 0.1;
03628: }
03629: }
03630:
03631: void wxFilteredDIB::applyImageMagickFiltering (struct _Image ** IMImage,
03632: struct _ExceptionInfo * exceptionInfo)
03633: {
03634: }
03635:
03636: void wxFilteredDIB::applyImageRotationMirroring (int RotationAngle,
03637: bool IsHorizontallyMirrored,
03638: bool IsVerticallyMirrored,
03639: WXHDIB & InputDIBHandle,
03640: WXHDIB & OutputDIBHandle,
03641: bool & IsNewOutputDIBHandle)
03642: {
03643: WXHDIB IntermediateDIBHandle = InputDIBHandle;
03644: WXHDIB PreviousIntermediateDIBHandle = InputDIBHandle;
03645:
03646: // rotate image data if required
03647: switch (RotationAngle)
03648: {
03649: case 90:
03650: IntermediateDIBHandle = applyDIBRotation (PreviousIntermediateDIBHandle, 90);
03651: break;
03652: case 180:
03653: IntermediateDIBHandle = applyDIBRotation (PreviousIntermediateDIBHandle, 180);
03654: break;
03655: case 270:
03656: IntermediateDIBHandle = applyDIBRotation (PreviousIntermediateDIBHandle, 270);
03657: break;
03658: }
03659:
03660: // clean up of temporary DIB's
03661: if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03662: && PreviousIntermediateDIBHandle != InputDIBHandle)
03663: {
03664: freeImage (PreviousIntermediateDIBHandle);
03665: }
03666: PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03667:
03668: // apply horizontal mirroring if required
03669: if (IsHorizontallyMirrored)
03670: {
03671: IntermediateDIBHandle = applyDIBMirroring (PreviousIntermediateDIBHandle, false);
03672: }
03673:
03674: // clean up of temporary DIB's
03675: if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03676: && PreviousIntermediateDIBHandle != InputDIBHandle)
03677: {
03678: freeImage (PreviousIntermediateDIBHandle);
03679: }
03680: PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03681:
03682: // apply vertical mirroring if required
03683: if (IsVerticallyMirrored)
03684: {
03685: IntermediateDIBHandle = applyDIBMirroring (PreviousIntermediateDIBHandle, true);
03686: }
03687:
03688: // clean up of temporary DIB's
03689: if (IntermediateDIBHandle != PreviousIntermediateDIBHandle
03690: && PreviousIntermediateDIBHandle != InputDIBHandle)
03691: {
03692: freeImage (PreviousIntermediateDIBHandle);
03693: }
03694: PreviousIntermediateDIBHandle = IntermediateDIBHandle;
03695:
03696: // set output variables
03697: OutputDIBHandle = PreviousIntermediateDIBHandle;
03698: IsNewOutputDIBHandle = InputDIBHandle != OutputDIBHandle;
03699: }
03700:
03701: //-------------------------------------------------------------------------
03702:
03703: void wxFilteredDIB::freeSourceImage()
03704: {
03705: if (m_IsOwningSourceImage)
03706: {
03707: freeImage (m_SourceDIBHandle);
03708: }
03709: }
03710:
03711: void wxFilteredDIB::freeResultImage()
03712: {
03713: if (m_IsOwningResultImage)
03714: {
03715: freeImage (m_ResultDIBHandle);
03716: }
03717: }
03718:
03719: void wxFilteredDIB::freeImage (WXHDIB & DIBHandle)
03720: {
03721: if (DIBHandle != NULL)
03722: {
03723: GlobalFree (DIBHandle);
03724: DIBHandle = NULL;
03725: }
03726: }
03727: #endif // wxUSE_GUI
03728:
03729: #endif // defined(__WXMSW__)
03730:
03731: #endif
03732:
03733: //=========================================================================
03734:
03735: wxChoiceManager::wxChoiceManager ()
03736: {
03737: m_FocusedSourceItemIndex = -1;
03738: m_FocusedChoiceItemIndex = -1;
03739: }
03740:
03741: void wxChoiceManager::OnSelect ()
03742: {
03743: selectIntoChoice (getChoiceFocus(), getSourceFocus());
03744: }
03745:
03746: void wxChoiceManager::OnDeselect ()
03747: {
03748: deselectFromChoice (getChoiceFocus());
03749: }
03750:
03751: void wxChoiceManager::OnClearSelection ()
03752: {
03753: int ChoiceItemCount = getChoiceItemCount ();
03754: for (int ChoiceItemIndex=0; ChoiceItemIndex<ChoiceItemCount; ++ChoiceItemIndex)
03755: {
03756: deselectFromChoice (ChoiceItemIndex, false);
03757: }
03758: updateChoiceView ();
03759: }
03760:
03761: void wxChoiceManager::OnSourceLeftMouseButton (int SourceItemIndex)
03762: {
03763: bool IsNewlyFocused = getSourceFocus () != SourceItemIndex;
03764:
03765: if (IsNewlyFocused)
03766: setSourceFocus (SourceItemIndex);
03767:
03768: handleSelection (IsNewlyFocused, getChoiceFocus (), SourceItemIndex);
03769: }
03770:
03771: void wxChoiceManager::OnSourceRightMouseButton (int SourceItemIndex)
03772: {
03773: int DocumentIdent = getSourceDocument (SourceItemIndex);
03774: deselectFromChoice (findChoiceItemIndex (DocumentIdent));
03775: }
03776:
03777: void wxChoiceManager::OnChoiceLeftMouseButton (int ChoiceItemIndex)
03778: {
03779: bool IsNewlyFocused = getChoiceFocus () != ChoiceItemIndex;
03780:
03781: if (IsNewlyFocused)
03782: setChoiceFocus (ChoiceItemIndex);
03783:
03784: handleSelection (IsNewlyFocused, ChoiceItemIndex, getSourceFocus());
03785: }
03786:
03787: void wxChoiceManager::OnChoiceRightMouseButton (int ChoiceItemIndex)
03788: {
03789: deselectFromChoice (ChoiceItemIndex);
03790: }
03791:
03792: //-------------------------------------------------------------------------
03793:
03794: void wxChoiceManager::handleSelection (bool IsNewlyFocused, int ChoiceItemIndex,
03795: int SourceItemIndex)
03796: {
03797: bool IsChoiceHavingDocument = getChoiceDocument (ChoiceItemIndex) != -1;
03798: bool IsDocumentAlreadyAssigned = findChoiceItemIndex (getSourceDocument (SourceItemIndex)) != -1;
03799:
03800: if ((!IsNewlyFocused || (!IsChoiceHavingDocument && !IsDocumentAlreadyAssigned))
03801: && SourceItemIndex != -1
03802: && ChoiceItemIndex != -1)
03803: {
03804: selectIntoChoice (ChoiceItemIndex, SourceItemIndex);
03805: }
03806: }
03807:
03808: //-------------------------------------------------------------------------
03809:
03810: void wxChoiceManager::selectIntoChoice (int ChoiceItemIndex, int SourceItemIndex,
03811: bool IsUpdateChoiceView)
03812: {
03813: int ChoiceItemCount = getChoiceItemCount();
03814:
03815: if (ChoiceItemIndex != -1 && SourceItemIndex != -1)
03816: {
03817: // create entries of -1 if necessary
03818: if (ChoiceItemIndex >= ChoiceItemCount)
03819: {
03820: insertChoiceDocument (-1, ChoiceItemCount, ChoiceItemIndex + 1 - ChoiceItemCount);
03821: }
03822:
03823: deselectFromChoice (ChoiceItemIndex,
03824: /* IsUpdateChoiceView */ false);
03825:
03826: setSelection (SourceItemIndex, true);
03827: int DocumentIdent = getSourceDocument (SourceItemIndex);
03828: setChoiceDocument (ChoiceItemIndex, DocumentIdent);
03829:
03830: if (IsUpdateChoiceView)
03831: updateChoiceView ();
03832: }
03833: }
03834:
03835: void wxChoiceManager::deselectFromChoice (int ChoiceItemIndex,
03836: bool IsUpdateChoiceView)
03837: {
03838: if (ChoiceItemIndex != -1 && ChoiceItemIndex < getChoiceItemCount())
03839: {
03840: int DocumentIdent = getChoiceDocument (ChoiceItemIndex);
03841:
03842: if (DocumentIdent != -1)
03843: {
03844: int SourceItemIndex = findSourceItemIndex (DocumentIdent);
03845: setChoiceDocument (ChoiceItemIndex, -1);
03846: int OtherChoiceItemIndex = findChoiceItemIndex (DocumentIdent);
03847: setSelection (SourceItemIndex, OtherChoiceItemIndex != -1);
03848:
03849: if (IsUpdateChoiceView)
03850: updateChoiceView ();
03851: }
03852: }
03853: }
03854:
03855: //-------------------------------------------------------------------------
03856:
03857: int wxChoiceManager::getSourceFocus ()
03858: {
03859: return m_FocusedSourceItemIndex;
03860: }
03861:
03862: void wxChoiceManager::setSourceFocus (int NewFocusedItemIndex)
03863: {
03864: if (NewFocusedItemIndex == m_FocusedSourceItemIndex)
03865: return;
03866:
03867: if (m_FocusedSourceItemIndex != -1)
03868: {
03869: updateSourceFocus (m_FocusedSourceItemIndex, false);
03870: }
03871: m_FocusedSourceItemIndex = NewFocusedItemIndex;
03872:
03873: if (m_FocusedSourceItemIndex != -1)
03874: {
03875: updateSourceFocus (m_FocusedSourceItemIndex, true);
03876: }
03877: }
03878:
03879: int wxChoiceManager::getChoiceFocus ()
03880: {
03881: return m_FocusedChoiceItemIndex;
03882: }
03883:
03884: void wxChoiceManager::setChoiceFocus (int NewFocusedItemIndex)
03885: {
03886: if (NewFocusedItemIndex == m_FocusedChoiceItemIndex)
03887: return;
03888:
03889: if (m_FocusedChoiceItemIndex != -1)
03890: {
03891: updateChoiceFocus (m_FocusedChoiceItemIndex, false);
03892: }
03893: m_FocusedChoiceItemIndex = NewFocusedItemIndex;
03894:
03895: if (m_FocusedChoiceItemIndex != -1)
03896: {
03897: updateChoiceFocus (m_FocusedChoiceItemIndex, true);
03898: }
03899: }
03900:
03901: void wxChoiceManager::redoSelections ()
03902: {
03903: int SourceItemCount = getSourceItemCount ();
03904: for (int SourceItemIndex=0; SourceItemIndex<SourceItemCount; ++SourceItemIndex)
03905: {
03906: int DocumentIdent = getSourceDocument (SourceItemIndex);
03907: setSelection (SourceItemIndex, findChoiceItemIndex (DocumentIdent) != -1);
03908: }
03909: updateChoiceView ();
03910: }
03911:
03912: void wxChoiceManager::setSelection (int SourceItemIndex, bool IsSelect)
03913: {
03914: if (SourceItemIndex == -1)
03915: return;
03916:
03917: updateSelection (SourceItemIndex, IsSelect);
03918: }
03919:
03920: //-------------------------------------------------------------------------
03921:
03922: int wxChoiceManager::findSourceItemIndex (int DocumentIdent)
03923: {
03924: int SourceDocumentCount = getSourceItemCount();
03925:
03926: for (int SourceDocumentIndex=0; SourceDocumentIndex<SourceDocumentCount; ++SourceDocumentIndex)
03927: {
03928: if (getSourceDocument (SourceDocumentIndex) == DocumentIdent)
03929: return SourceDocumentIndex;
03930: }
03931:
03932: return -1;
03933: }
03934:
03935: int wxChoiceManager::findChoiceItemIndex (int DocumentIdent)
03936: {
03937: int ChoiceDocumentCount = getChoiceItemCount ();
03938:
03939: for (int ChoiceDocumentIndex=0; ChoiceDocumentIndex<ChoiceDocumentCount; ++ChoiceDocumentIndex)
03940: {
03941: if (getChoiceDocument (ChoiceDocumentIndex) == DocumentIdent)
03942: return ChoiceDocumentIndex;
03943: }
03944:
03945: return -1;
03946: }
03947:
03948: //=========================================================================
03949:
03950: wxDefaultParentWindowFunc s_GlobalDefaultParentWindowFunc = NULL;
03951:
03952: void wxSetGlobalDefaultParentWindowFunc (wxDefaultParentWindowFunc Func)
03953: {
03954: s_GlobalDefaultParentWindowFunc = Func;
03955: }
03956:
03957: wxDefaultParentWindowFunc wxGetGlobalDefaultParentWindowFunc ()
03958: {
03959: return s_GlobalDefaultParentWindowFunc;
03960: }
03961:
03962: wxWindow * wxGetDefaultParentWindow (wxWindow * ParentWindow)
03963: {
03964: if (ParentWindow != NULL)
03965: return ParentWindow;
03966:
03967: if (s_GlobalDefaultParentWindowFunc != NULL)
03968: {
03969: return s_GlobalDefaultParentWindowFunc (ParentWindow);
03970: }
03971:
03972: // return ParentWindow, which is NULL here
03973: return ParentWindow;
03974: }
03975:
03976: //=========================================================================
03977: