1%% options 2copyright owner = Dirk Krause 3copyright year = 2019-xxxx 4SPDX-License-Identifier: BSD-3-Clause 5 6 7 8%% wx-gui 9 10type = frame 11contents = mainSizer 12icon = wximgsz_icon 13status bar = 1 sTexts[8] 14menu bar = mbMain 15 16[wxMenuBar mbMain] 17contents = menuFile 18contents = menuHelp 19 20[wxMenu menuFile] 21text = sTexts[0] 22contents = miFileOpen 23contents = miFileExit 24 25[wxMenuItem miFileOpen] 26id = wxID_OPEN 27text = sTexts[40] 28tip = sTexts[41] 29 30[wxMenuItem miFileExit] 31id = wxID_EXIT 32text = sTexts[1] 33tip = sTexts[2] 34 35[wxMenu menuHelp] 36text = sTexts[3] 37contents = miHelpAbout 38contents = miHelpContents 39 40[wxMenuItem miHelpAbout] 41id = WximgszFrame::ID_HELP_ABOUT 42text = sTexts[4] 43tip = sTexts[5] 44 45[wxMenuItem miHelpContents] 46id = WximgszFrame::ID_HELP_TOC 47text = sTexts[6] 48tip = sTexts[7] 49 50[wxBoxSizer mainSizer] 51direction = horizontal 52contents = $space(10) 53contents = verticalSizer 54contents = $space(10) 55 56[wxBoxSizer verticalSizer] 57direction = vertical 58grow = yes 59proportion = 1 60contents = $space(10) 61contents = contentsSizer 62contents = $space(10) 63 64[wxBoxSizer contentsSizer] 65direction = horizontal 66grow = yes 67proportion = 1 68contents = inputSizer 69contents = $space(20,20) 70contents = runButtonSizer 71contents = $space(20,20) 72contents = resultSizer 73 74[wxGridBagSizer inputSizer] 75grid = 5 5 76contents = lInput 0 0 1 2 left 77contents = lInputWidth +1 0 1 1 right centered-y 78contents = spInputWidth . +1 1 1 centered-y 79contents = lInputHeight +1 0 1 1 right centered-y 80contents = spInputHeight . +1 1 1 centered-y 81contents = $space(10) +1 0 1 1 82contents = lChange +1 0 1 2 left 83contents = lOperation +1 0 1 1 right centered-y 84contents = cbOperation . +1 1 1 left centered-y 85contents = lOperationMin +1 0 1 1 right centered-y 86contents = spOperationMin . +1 1 1 left centered-y 87contents = lOperationMax +1 0 1 1 right centered-y 88contents = spOperationMax . +1 1 1 left centered-y 89 90[wxBoxSizer runButtonSizer] 91grow = yes 92direction = vertical 93contents = $stretch(10) 94contents = bRun 95contents = $stretch(10) 96 97[wxBoxSizer resultSizer] 98grow = yes 99proportion = 1 100direction = vertical 101contents = lResults left 102contents = tResult left 103 104[wxStaticText lInput] 105text = sTexts[13] 106 107[wxStaticText lResults] 108text = sTexts[28] 109 110[wxStaticText lInputWidth] 111text = sTexts[14] 112 113[wxStaticText lInputHeight] 114text = sTexts[15] 115 116[wxSpinCtrl spInputWidth] 117value = 1 118range = 1 65535 119tip = sTexts[16] 120 121[wxBitmapButton bRun] 122tip = sTexts[29] 123bitmap = xpm_run_conversion 124id = ID_BUTTON_RUN 125 126[wxGrid tResult] 127text style = readonly 128column head = sTexts[30] 129column head = sTexts[31] 130column head = sTexts[32] 131column head = sTexts[33] 132rows = 4 133# minimum size = 150 100 134grow = true 135proportion = 1 136 137[wxSpinCtrl spInputHeight] 138value = 1 139range = 1 65535 140tip = sTexts[17] 141 142[wxStaticText lChange] 143text = sTexts[18] 144 145[wxStaticText lOperation] 146text = sTexts[19] 147 148[wxChoice cbOperation] 149id = ID_CHOICE_OP 150choices = 3 saOperation 151tip = sTexts[20] 152proportion = 1 153 154[wxStaticText lOperationMin] 155text = sTexts[24] 156 157[wxSpinCtrl spOperationMin] 158value = 1 159range = 1 65535 160tip = sTexts[26] 161 162[wxStaticText lOperationMax] 163text = sTexts[25] 164 165[wxSpinCtrl spOperationMax] 166value = 1 167range = 1 65535 168tip = sTexts[27] 169 170%% header start 171 172 173 174%% class start 175class WximgszFrame : public Dk4WxFrame 176{ 177 private: 178 179 /** Event table for frame. 180 */ 181 DECLARE_EVENT_TABLE() 182 183 protected: 184 185 /** Auto start controller. 186 */ 187 Dk4WxAutostartController cas; 188 189 /** Dark red text colour for group labels. 190 */ 191 wxColour cLabelRed; 192 193 /** Light red background for table cells. 194 */ 195 wxColour cRed; 196 197 /** Light green background for table cells. 198 */ 199 wxColour cGreen; 200 201 /** Yellow background for table cells. 202 */ 203 wxColour cYellow; 204 205 /** Text colour for table cells. 206 */ 207 wxColour cBlack; 208 209 /** Image file name to process on autostart. 210 */ 211 wxString sImageFileName; 212 213 /** Directory previous image file was read from. 214 */ 215 wxString sDirectory; 216 217 /** Localized texts. 218 */ 219 wxChar const * const *sTexts; 220 221 /** Non-localized texts. 222 */ 223 wxChar const * const *sNlWx; 224 225 /** Non-localized texts. 226 */ 227 dkChar const * const *sNlDk; 228 229 /* __CHANGE__ 011: Add further member variables. 230 */ 231 232 /** Maximum number of items in grid. 233 */ 234 int maxpass; 235 236 /** Have image file name. 237 */ 238 bool bImageFileName; 239 240 /** Flag: Application should still respond to onidle. 241 */ 242 bool bActive; 243 244 /** Process the file name which was specified on command line. 245 */ 246 void 247 ProcessSpecifiedFileName(void); 248 249%% class end 250 251 public: 252 253 /** Window IDs used in main window (frame). 254 */ 255 enum { 256 ID_FRAME = (wxID_HIGHEST + 1), /**< Frame. */ 257 ID_HELP_ABOUT , /**< Open information dialog box. */ 258 ID_HELP_TOC , /**< Open help table of contents. */ 259 ID_BUTTON_RUN , /**< Button to run calculation. */ 260 ID_CHOICE_OP , /**< Choice box for operation. */ 261 }; 262 263 /** Maximum number of passes. 264 */ 265 enum { 266 MAXPASS = 2000 267 }; 268 269 /** Maximum image dimension adjustable in spin control. 270 */ 271 enum { 272 /** Maximum image dimension adjustable in spin control. 273 */ 274 MAXIMGDIM = 65535 275 }; 276 277 /** Constructor. 278 @param wxid Window ID. 279 @param applicationHelper Application helper object. 280 @param hc Help controller for online help. 281 @param argc Number of command line arguments. 282 @param argv Command line arguments array. 283 @param localizedTexts Localized wxChar texts. 284 @param nlWx Non-localized wxChar texts. 285 @param nlDk Non-localized dkChar texts. 286 */ 287 WximgszFrame( 288 int wxid, 289 Dk4WxApplicationHelper *applicationHelper, 290 Dk4WxHelpController *hc, 291 int argc, 292 wxChar **argv, 293 wxChar const * const *localizedTexts, 294 wxChar const * const *nlWx, 295 dkChar const * const *nlDk 296 ); 297 298 /** Destructor. 299 */ 300 ~WximgszFrame(); 301 302 /** Check whether we can close the window. 303 @param isLast Flag: Last main window to close. 304 */ 305 bool 306 CanClose(bool isFinal); 307 308 /** Handler for File/Open. 309 @param event Event to process. 310 */ 311 void 312 OnFileOpen(wxCommandEvent & event); 313 314 /** Handler for File/Exit. 315 @param event Event to process. 316 */ 317 void 318 OnQuit(wxCommandEvent & event); 319 320 /** Handler for Help/About. 321 @param event Event to process. 322 */ 323 void 324 OnAbout(wxCommandEvent & event); 325 326 /** Handler for Help/Contents. 327 @param event Event to process. 328 */ 329 void 330 OnHelpContents(wxCommandEvent & event); 331 332 /** Do the calculations and update table. 333 */ 334 void 335 Calculations(void); 336 337 /** Handler for Run button. 338 @param event Event to process. 339 */ 340 void 341 OnButtonRun(wxCommandEvent & event); 342 343 /** Handler for operations choice box. 344 @param event Event to process. 345 */ 346 void 347 OnChoiceOperation(wxCommandEvent & event); 348 349 /* __CHANGE__ 008: Remove OnIdle if no idle processing required. 350 */ 351 /** Handler for idle events. 352 */ 353 void 354 OnIdle(wxIdleEvent & event); 355 356 /* __CHANGE__ 017: Event handlers for further events. 357 */ 358 359 /* __CHANGE__ 014: Add further methods. 360 */ 361 362 /** Activate or deactivate idle processing. 363 @param fl Flag to activate/deactivate. 364 */ 365 void 366 ActivateIdleProcessing(bool fl = true); 367 368}; 369 370%% header end 371 372 373/* vim: set ai sw=4 ts=4 : */ 374%% module start 375 376#include <wximgsz/wximgsz.h> 377 378 379#if !defined(__WXMSW__) 380#include "gui-img/icons/dkicon.xpm" 381#endif 382 383 384#include "gui-img/shared/toolbar/run-conversion.xpm" 385 386 387$!trace-include 388 389 390 391/* __CHANGE__ 017: Add further events. */ 392 393/* Hint: Window IDs for main frame members are defined in an enum 394 in the frame class. 395 IDs defined in this enum should have WximgszFrame:: prepended 396 for an optical distinction from predefined window IDs (i.e. from 397 wxWidgets). 398*/ 399 400/* __CHANGE__ 008: Remove OnIdle if no idle processing required. 401 When removing the table entry here, remove the entire OnIdle() method. 402*/ 403 404#if wxCHECK_VERSION(3,0,0) 405wxBEGIN_EVENT_TABLE(WximgszFrame,wxFrame) 406#else 407BEGIN_EVENT_TABLE(WximgszFrame,wxFrame) 408#endif 409 EVT_MENU(\ 410 wxID_OPEN,\ 411 WximgszFrame::OnFileOpen\ 412 ) 413 EVT_MENU(\ 414 wxID_EXIT,\ 415 WximgszFrame::OnQuit\ 416 ) 417 EVT_MENU(\ 418 WximgszFrame::ID_HELP_ABOUT,\ 419 WximgszFrame::OnAbout\ 420 ) 421 EVT_MENU(\ 422 WximgszFrame::ID_HELP_TOC,\ 423 WximgszFrame::OnHelpContents\ 424 ) 425 EVT_BUTTON(\ 426 WximgszFrame::ID_BUTTON_RUN,\ 427 WximgszFrame::OnButtonRun\ 428 ) 429 EVT_CHOICE(\ 430 WximgszFrame::ID_CHOICE_OP,\ 431 WximgszFrame::OnChoiceOperation\ 432 ) 433 EVT_IDLE(\ 434 WximgszFrame::OnIdle\ 435 ) 436#if wxCHECK_VERSION(3,0,0) 437wxEND_EVENT_TABLE() 438#else 439END_EVENT_TABLE() 440#endif 441 442 443 444/** Image file types we can handle. 445*/ 446static wxChar const image_files_to_open[] = { 447 wxT("All files (*.*)|*.*") 448#if wxUSE_LIBPNG 449 wxT("|PNG files (*.png)|*.png") 450#endif 451#if wxUSE_LIBJPEG 452 wxT("|JPEG files (*.jpeg)|*.jpeg") 453 wxT("|JPEG files (*.jpg)|*.jpg") 454#endif 455#if wxUSE_LIBTIFF 456 wxT("|TIFF files (*.tiff)|*.tiff") 457 wxT("|TIFF files (*.tif)|*.tif") 458#endif 459#if wxUSE_GIF 460 wxT("|GIF files (*.gif)|*.gif") 461#endif 462#if wxUSE_PCX 463 wxT("|PCX files (*.pcx)|*.pcx") 464#endif 465 wxT("|BMP files (*.bmp)|*.bmp") 466#if wxUSE_ICO_CUR 467 wxT("|ICO files (*.ico)|*.ico") 468 wxT("|CUR files (*.cur)|*.cur") 469#endif 470#if wxUSE_XPM 471 wxT("|XPM files (*.xpm)|*.xpm") 472 wxT("|XBM files (*.xbm)|*.xbm") 473#endif 474#if wxUSE_TGA 475 wxT("|TGA files (*.tga)|*.tga") 476#endif 477#if wxUSE_IFF 478 wxT("|IFF files (*.iff)|*.iff") 479#endif 480 wxT("|ANI files (*.ani)|*.ani") 481#if wxUSE_PNM 482 wxT("|NetPBM files (*.pam)|*.pam") 483 wxT("|NetPBM files (*.pnm)|*.pnm") 484 wxT("|NetPBM files (*.ppm)|*.ppm") 485 wxT("|NetPBM files (*.pgm)|*.pgm") 486 wxT("|NetPBM files (*.pbm)|*.pbm") 487#endif 488}; 489 490 491/** Suffix and bitmap type relationship. 492*/ 493typedef struct { 494 wxChar const *s; /**< File name suffix. */ 495 wxBitmapType t; /**< Bitmap type. */ 496} Suffix_and_type_t; 497 498 499 500/** Array to assign file name suffixes to file types. 501*/ 502Suffix_and_type_t suffix_and_type[] = { 503#if wxUSE_LIBPNG 504 { wxT(".png"), wxBITMAP_TYPE_PNG }, 505#endif 506#if wxUSE_LIBJPEG 507 { wxT(".jpeg"), wxBITMAP_TYPE_JPEG }, 508 { wxT(".jpg"), wxBITMAP_TYPE_JPEG }, 509#endif 510#if wxUSE_LIBTIFF 511 { wxT(".tiff"), wxBITMAP_TYPE_TIFF }, 512 { wxT(".tif"), wxBITMAP_TYPE_TIF }, 513#endif 514#if wxUSE_PNM 515 { wxT(".pam"), wxBITMAP_TYPE_PNM }, 516 { wxT(".pnm"), wxBITMAP_TYPE_PNM }, 517 { wxT(".ppm"), wxBITMAP_TYPE_PNM }, 518 { wxT(".pgm"), wxBITMAP_TYPE_PNM }, 519 { wxT(".pbm"), wxBITMAP_TYPE_PNM }, 520#endif 521#if wxUSE_XPM 522 { wxT(".xpm"), wxBITMAP_TYPE_XPM }, 523 { wxT(".xbm"), wxBITMAP_TYPE_XBM }, 524#endif 525#if wxUSE_ICO_CUR 526 { wxT(".ico"), wxBITMAP_TYPE_ICO }, 527 { wxT(".cur"), wxBITMAP_TYPE_CUR }, 528#endif 529#if wxUSE_GIF 530 { wxT(".gif"), wxBITMAP_TYPE_GIF }, 531#endif 532#if wxUSE_PCX 533 { wxT(".pcx"), wxBITMAP_TYPE_PCX }, 534#endif 535 { wxT(".bmp"), wxBITMAP_TYPE_BMP }, 536#if wxUSE_TGA 537 { wxT(".tga"), wxBITMAP_TYPE_TGA }, 538#endif 539#if wxUSE_IFF 540 { wxT(".iff"), wxBITMAP_TYPE_IFF }, 541#endif 542 { wxT(".ani"), wxBITMAP_TYPE_ANI }, 543 { NULL, wxBITMAP_TYPE_INVALID } 544}; 545 546 547 548static 549wxBitmapType 550bitmap_type_for_name(wxString & fn) 551{ 552 wxChar const *ptr = NULL; 553 Suffix_and_type_t *sat = NULL; 554 wxBitmapType back = wxBITMAP_TYPE_INVALID; 555 wxCStrData strdata = fn.c_str(); 556 ptr = (wxChar const *)strdata; 557 if (NULL != ptr) { 558 ptr = dk4strx_get_path_suffix(ptr, NULL); 559 if (NULL != ptr) { 560 sat = suffix_and_type; 561 while((NULL != sat->s) && (wxBITMAP_TYPE_INVALID == back)) { 562 if (0 == dk4strx_casecmp(sat->s, ptr)) { 563 back = sat->t; 564 } 565 else { 566 sat++; 567 } 568 } 569 } 570 } 571 return back; 572} 573 574 575 576%% constructor start 577WximgszFrame::WximgszFrame( 578 int wxid, 579 Dk4WxApplicationHelper *applicationHelper, 580 Dk4WxHelpController *hc, 581 int argc, 582 wxChar **argv, 583 wxChar const * const *localizedTexts, 584 wxChar const * const *nlWx, 585 dkChar const * const *nlDk 586) : Dk4WxFrame(nlWx[0], applicationHelper, hc, wxid), 587 cas(), 588 cLabelRed(127, 0, 0), 589 cRed(255, 91, 91), 590 cGreen(127, 255, 127), 591 cYellow(255, 255, 0), 592 cBlack(0, 0, 0), 593 sImageFileName((1 < argc)?(argv[1]):(wxT(""))), 594 sDirectory(wxEmptyString) 595{ 596 wxString saOperation[] = { 597 wxString(localizedTexts[21]), 598 wxString(localizedTexts[22]), 599 wxString(localizedTexts[23]) 600 }; 601 $? "+ WximgszFrame::WximgszFrame" 602 /* __CHANGE__ 012: Add further local variables. 603 */ 604 605 /* __CHANGE__ 012: Initialize further local variables. 606 */ 607 608 sTexts = localizedTexts; 609 sNlWx = nlWx; 610 sNlDk = nlDk; 611#if defined(__WXMSW__) 612 wxIcon wximgsz_icon(sNlWx[4]); 613#else 614 wxIcon wximgsz_icon(xpm_dkicon); 615#endif 616 617 /* __CHANGE__ 011: Initialize further class members. 618 */ 619 maxpass = MAXPASS; 620 bActive = false; 621 bImageFileName = false; 622 if (1 < argc) { 623 bImageFileName = true; 624 cas.SetAutoStart(); 625 } 626 627%% constructor end 628 if(dkctGUILayoutOK) { 629 lInput->SetForegroundColour(cLabelRed); 630 lChange->SetForegroundColour(cLabelRed); 631 lResults->SetForegroundColour(cLabelRed); 632#if 0 633 spInputWidth->SetRange(1, INT_MAX); 634 spInputHeight->SetRange(1, INT_MAX); 635 spOperationMin->SetRange(1, INT_MAX); 636 spOperationMax->SetRange(1, INT_MAX); 637 inputSizer->Fit(spInputWidth); 638 inputSizer->Fit(spInputHeight); 639 inputSizer->Fit(spOperationMin); 640 inputSizer->Fit(spOperationMax); 641 mainSizer->Layout(); 642#endif 643 cbOperation->SetSelection(0); 644 spOperationMin->Enable(false); 645 spOperationMax->Enable(false); 646 SetTitle(nlWx[0]); 647#if 0 648 RestorePosition(); 649#endif 650 } 651 652 /* __CHANGE__ 012: Release resources allocated by local variables. 653 */ 654 655 $? "- WximgszFrame::WximgszFrame" 656} 657 658%% module end 659 660 661 662WximgszFrame::~WximgszFrame() 663{ 664 $? "+ WximgszFrame::~WximgszFrame" 665 666 /* __CHANGE__ 011: Release resources allocated by further class members. 667 */ 668 669 $? "- WximgszFrame::~WximgszFrame" 670} 671 672 673 674bool 675WximgszFrame::CanClose(bool WXUNUSED(isLast)) 676{ 677 bool back = true; 678 $? "+ WximgszFrame::CanClose" 679 680 /* __CHANGE__ 013: Check for unsaved data. 681 And probably change parameter to "bool WXUNUSED(isLast)" 682 */ 683 684 $? "- WximgszFrame::CanClose %d", (back ? 1 : 0) 685 return back; 686} 687 688 689 690void 691WximgszFrame::OnFileOpen(wxCommandEvent & WXUNUSED(event)) 692{ 693 dkChar buf[DK4_MAX_PATH]; 694 dk4_bif_t *pbif; 695 const wxChar *ptrFilePath; 696 bool success = false; 697 int dke; 698 int wxe; 699 int res; 700#if wxCHECK_VERSION(2, 9, 0) 701 wxFileDialog dlg( 702 this, sTexts[42], sDirectory, wxEmptyString, 703 image_files_to_open, (wxFD_OPEN | wxFD_FILE_MUST_EXIST) 704 ); 705#else 706 wxFileDialog dlg( 707 this, sTexts[42], sDirectory, wxEmptyString, 708 image_files_to_open, wxOPEN 709 ); 710#endif 711 $? "+ OnFileOpen" 712 if(wxID_OK == dlg.ShowModal()) { 713 wxString pa = dlg.GetPath(); 714 wxFileName wxfn(pa); 715 if (wxfn.FileExists() && wxfn.IsFileReadable()) { 716 sDirectory = dlg.GetDirectory(); 717 { 718 wxCStrData sFilePath = pa.c_str(); 719 ptrFilePath = (wxChar const *)sFilePath; 720 if (NULL != ptrFilePath) { 721 dke = pAppHelp->GetDkEncoding(); 722 wxe = pAppHelp->GetWxEncoding(); 723 res = dk4recwx_wxchar_to_dkchar( 724 buf, DK4_SIZEOF(buf,dkChar), dke, ptrFilePath, wxe, NULL 725 ); 726 if (0 != res) { 727 pbif = dk4bif_open(buf, 1, NULL, NULL); 728 if (NULL != pbif) { 729 dk4_bif_dim_t w = dk4bif_get_width(pbif); 730 dk4_bif_dim_t h = dk4bif_get_height(pbif); 731 if ( 732 ((dk4_im_t)0L < (dk4_im_t)w) 733 && ((dk4_im_t)0L < (dk4_im_t)h) 734 && ((dk4_im_t)(MAXIMGDIM) >= (dk4_im_t)w) 735 && ((dk4_im_t)(MAXIMGDIM) >= (dk4_im_t)h) 736 ) { 737 spInputWidth->SetValue((int)w); 738 spInputHeight->SetValue((int)h); 739 success = true; 740 } 741 dk4bif_close(pbif); 742 } 743 } 744 } 745 } 746 if (!(success)) { $? ". no success yet" 747 wxBitmapType t = bitmap_type_for_name(pa); 748 if (wxBITMAP_TYPE_INVALID != t) { $? ". file suffix ok" 749 wxBitmap bm(pa, t); 750 if (bm.IsOk()) { 751 int w = bm.GetWidth(); 752 int h = bm.GetHeight(); 753 if ((0 < w) && (0 < h)) { 754 spInputWidth->SetValue(w); 755 spInputHeight->SetValue(h); 756 success = true; 757 } 758 else { $? "! dimensions" 759 wxMessageBox( 760 sTexts[44], sTexts[43], 761 (wxOK | wxCENTRE | wxICON_ERROR) 762 ); 763 } 764 } 765 else { $? "! bitmap not ok" 766 wxMessageBox( 767 sTexts[44], sTexts[43], 768 (wxOK | wxCENTRE | wxICON_ERROR) 769 ); 770 } 771 } 772 else { 773 wxString s(sTexts[49]); 774 s.Append(pa); 775 s.Append(sTexts[50]); 776 wxMessageBox( 777 s, wxString(sTexts[43]), (wxOK | wxCENTRE | wxICON_ERROR) 778 ); 779 } 780 } 781 if(success) { 782 Calculations(); 783 } 784 } 785 else { 786 if (!(wxfn.FileExists())) { $? "! no such file" 787 wxString s(sTexts[45]); 788 s.Append(pa); 789 s.Append(sTexts[46]); 790 wxMessageBox( 791 s, wxString(sTexts[43]), (wxOK | wxCENTRE | wxICON_ERROR) 792 ); 793 } 794 else { 795 if (!(wxfn.IsFileReadable())) { $? "! permissions" 796 wxString s(sTexts[47]); 797 s.Append(pa); 798 s.Append(sTexts[48]); 799 wxMessageBox( 800 s,wxString(sTexts[43]),(wxOK | wxCENTRE | wxICON_ERROR) 801 ); 802 } 803 } 804 } 805 } 806 $? "- OnFileOpen" 807 Refresh(); 808 Update(); 809} 810 811 812void 813WximgszFrame::OnQuit(wxCommandEvent & WXUNUSED(event)) 814{ 815 $? "+ WximgszFrame::OnQuit" 816 bActive = false; 817 $? "- WximgszFrame::OnQuit" 818 Close(); 819} 820 821 822 823void 824WximgszFrame::OnAbout(wxCommandEvent & WXUNUSED(event)) 825{ 826 wxString text(wxT("")); 827 wxString title(wxT("")); 828 $? "+ WximgszFrame::OnAbout" 829 /* Construct message text. */ 830 text.Append(sNlWx[0]); 831 text.Append(sNlWx[7]); 832#if 0 833 text.Append(sNlWx[1]); 834#endif 835 text.Append(DKT_VERSION_WX); 836 text.Append(sNlWx[8]); 837 text.Append(sTexts[9]); 838 text.Append(sNlWx[2]); 839 text.Append(sNlWx[8]); 840 text.Append(sNlWx[8]); 841 text.Append(sTexts[11]); 842 text.Append(sNlWx[8]); 843 text.Append(sNlWx[9]); 844 text.Append(sNlWx[8]); 845 text.Append(sNlWx[8]); 846 text.Append(sTexts[12]); 847 text.Append(sNlWx[8]); 848 text.Append(sNlWx[10]); 849 text.Append(sNlWx[8]); 850 text.Append(sNlWx[11]); 851 text.Append(sNlWx[8]); 852 text.Append(sNlWx[12]); 853 text.Append(sNlWx[8]); 854 text.Append(sNlWx[13]); 855 text.Append(sNlWx[8]); 856 text.Append(sNlWx[14]); 857 text.Append(sNlWx[8]); 858 text.Append(sNlWx[15]); 859 text.Append(sNlWx[8]); 860 861 /* Construct dialog box title. */ 862 title.Append(sTexts[10]); 863 title.Append(sNlWx[0]); 864 865 /* Show dialog box. */ 866 wxMessageBox(text, title); 867 868 /* __CHANGE__ 019: Create better about box. 869 */ 870 $? "- WximgszFrame::OnAbout" 871} 872 873 874 875void 876WximgszFrame::OnHelpContents(wxCommandEvent & WXUNUSED(event)) 877{ 878 $? "+ WximgszFrame::OnHelpContents" 879 DisplayContents(); 880 $? "- WximgszFrame::OnHelpContents" 881} 882 883 884 885static 886int 887bits_in_int(int x) 888{ 889 int back = 0; 890 int test = 1; 891 int done = 0; 892 893 while (0 == done) { 894 if (0 != (x & test)) { 895 if (1 < ++back) { 896 done = 1; 897 } 898 } 899 if ((INT_MAX / 2) >= test) { 900 test = test * 2; 901 if (test > x) { 902 done = 1; 903 } 904 } 905 else { 906 done = 1; 907 } 908 } 909 return back; 910} 911 912 913static 914int 915is_power_of_2(int x) 916{ 917 int back = 0; 918 if (1 == bits_in_int(x)) { 919 back = 1; 920 } 921 return back; 922} 923 924 925 926static 927int 928quality_for_fraction(int counter, int denom) 929{ 930 int back = 0; 931 if (1 == denom) { 932 back = 1; 933 if (0 != is_power_of_2(counter)) { 934 back = 2; 935 } 936 } 937 else { 938 if (1 == counter) { 939 back = 1; 940 if (0 != is_power_of_2(denom)) { 941 back = 2; 942 } 943 } 944 } 945 return back; 946} 947 948 949 950static 951int 952gcd(int a, int b) 953{ 954 int h; 955 $? "+ gcd a=%d b=%d", a, b 956 while (0 < b) { 957 h = a % b; 958 a = b; 959 b = h; 960 } $? "- gcd %d", a 961 return a; 962} 963 964 965/* __CHANGE__ 017: Event handlers for further events. 966*/ 967 968void 969WximgszFrame::Calculations(void) 970{ 971 wxString s1; /* Width */ 972 wxString s2; /* Height */ 973 wxString s3; /* Factor */ 974 wxString m2(sTexts[36]); 975 wxString m1(sTexts[35]); 976 wxString m0(sTexts[34]); 977 int w_ori; /* Original width */ 978 int h_ori; /* Original height */ 979 int w_min; /* Minimum width */ 980 int h_min; /* Minimum height */ 981 int gcd_ori; /* Greatest common divisor original width height */ 982 int min; /* Destination range minimum */ 983 int max; /* Destination range maximum */ 984 int opsel; /* Operation selection */ 985 int f_min; /* Minimum factor */ 986 int f_max; /* Maximum factor */ 987 int nrows; /* Number of table rows */ 988 int passno; /* Current pass number (table row index) */ 989 int f; /* Current factor */ 990 int w; /* Current width */ 991 int h; /* Current height */ 992 int counter; /* Fraction counter */ 993 int denom; /* Fraction denominator */ 994 int gcd_fr; /* Fraction greatest common divisor */ 995 int q; /* Fraction quality */ 996 int i; /* Walk through the columns */ 997 bool bDidSkip; /* Flag: Restricted output to 2000 columns */ 998 $? "+ Calculations" 999 bDidSkip = false; 1000 w_ori = spInputWidth->GetValue(); 1001 h_ori = spInputHeight->GetValue(); 1002 min = spOperationMin->GetValue(); 1003 max = spOperationMax->GetValue(); 1004 opsel = cbOperation->GetSelection(); 1005 if (0 >= w_ori) { w_ori = 1; } 1006 if (0 >= h_ori) { h_ori = 1; } 1007 if (0 >= min) { min = 1; } 1008 if (0 >= max) { max = 1; } 1009 gcd_ori = gcd(w_ori, h_ori); 1010 w_min = w_ori / gcd_ori; 1011 h_min = h_ori / gcd_ori; 1012 f_min = 1; 1013 f_max = gcd_ori; 1014 switch (opsel) { 1015 case 1: { 1016 f_min = min / w_min; 1017 f_max = max / w_min; 1018 if (0 >= f_min) { f_min = 1; } 1019 if (0 >= f_max) { f_max = 1; } 1020 } break; 1021 case 2: { 1022 f_min = min / h_min; 1023 f_max = max / h_min; 1024 if (0 >= f_min) { f_min = 1; } 1025 if (0 >= f_max) { f_max = 1; } 1026 } break; 1027 } 1028 nrows = f_max - f_min + 1; 1029 if (nrows > maxpass) { nrows = maxpass; bDidSkip = true; } 1030 /* 1031 Delete old table columns, allocate new columns 1032 */ 1033 passno = tResult->GetNumberRows(); 1034 tResult->DeleteRows(0, passno); 1035 tResult->AppendRows(nrows); 1036 /* 1037 Fill table 1038 */ 1039 passno = 0; 1040 f = f_min; 1041 while (passno < nrows) { 1042 w = f * w_min; 1043 h = f * h_min; 1044 gcd_fr = gcd(f, gcd_ori); 1045 counter = f / gcd_fr; 1046 denom = gcd_ori / gcd_fr; 1047 q = quality_for_fraction(counter, denom); 1048 s1.Printf(wxT("%d"), w); 1049 s2.Printf(wxT("%d"), h); 1050 if (1 == denom) { 1051 s3.Printf(wxT("%d"), counter); 1052 } 1053 else { 1054 s3.Printf(wxT("%d / %d"), counter, denom); 1055 } 1056 for (i = 0; i < 4; i++) { 1057 tResult->SetCellTextColour(passno, i, cBlack); 1058 } 1059 tResult->SetCellValue(passno, 0, s1); 1060 tResult->SetCellValue(passno, 1, s2); 1061 tResult->SetCellValue(passno, 2, s3); 1062 switch (q) { 1063 case 2: { 1064 tResult->SetCellValue(passno, 3, m2); 1065 for (i = 0; i < 4; i++) { 1066 tResult->SetCellBackgroundColour( 1067 passno, i, cGreen 1068 ); 1069 } 1070 } break; 1071 case 1: { 1072 tResult->SetCellValue(passno, 3, m1); 1073 for (i = 0; i < 4; i++) { 1074 tResult->SetCellBackgroundColour( 1075 passno, i, cYellow 1076 ); 1077 } 1078 } break; 1079 case 0: { 1080 tResult->SetCellValue(passno, 3, m0); 1081 for (i = 0; i < 4; i++) { 1082 tResult->SetCellBackgroundColour( 1083 passno, i, cRed 1084 ); 1085 } 1086 } break; 1087 } 1088 tResult->SetCellAlignment(passno, 0, wxALIGN_CENTRE, wxALIGN_CENTRE); 1089 tResult->SetCellAlignment(passno, 1, wxALIGN_CENTRE, wxALIGN_CENTRE); 1090 tResult->SetCellAlignment(passno, 2, wxALIGN_CENTRE, wxALIGN_CENTRE); 1091 tResult->SetCellAlignment(passno, 3, wxALIGN_CENTRE, wxALIGN_CENTRE); 1092 passno++; 1093 f++; 1094 } 1095 tResult->AutoSizeColumns(); 1096 tResult->EnableDragColSize(true); 1097 if (bDidSkip) { 1098 wxMessageBox( sTexts[39], sTexts[38], (wxOK | wxCENTRE | wxICON_ERROR)); 1099 } 1100 $? "- Calculations" 1101} 1102 1103 1104 1105void 1106WximgszFrame::OnButtonRun(wxCommandEvent & WXUNUSED(event)) 1107{ 1108 $? "+ OnButtonRun" 1109 Calculations(); 1110 $? "- OnButtonRun" 1111 Refresh(); 1112 Update(); 1113} 1114 1115 1116 1117void 1118WximgszFrame::OnChoiceOperation(wxCommandEvent & WXUNUSED(event)) 1119{ 1120 $? "+ OnChoiceOperation" 1121 switch (cbOperation->GetSelection()) { 1122 case 2 : case 1 : { 1123 spOperationMin->Enable(); 1124 spOperationMax->Enable(); 1125 } break; 1126 default : { 1127 spOperationMin->Enable(false); 1128 spOperationMax->Enable(false); 1129 } break; 1130 } 1131 $? "- OnChoiceOperation" 1132 Refresh(); 1133 Update(); 1134} 1135 1136 1137/* __CHANGE__ 014: Implementation of further methods. 1138*/ 1139 1140 1141void 1142WximgszFrame::ActivateIdleProcessing(bool fl) 1143{ 1144 bActive = fl; 1145} 1146 1147 1148void 1149WximgszFrame::ProcessSpecifiedFileName(void) 1150{ 1151 dkChar buf[DK4_MAX_PATH]; 1152 wxChar const *ptrImageFileName; 1153 dk4_bif_t *pbif; 1154 int dke; 1155 int wxe; 1156 int res; 1157 bool success; 1158 $? "+ ProcessSpecifiedFileName" 1159 success = false; 1160 wxFileName wxfn(sImageFileName); 1161 if (wxfn.FileExists() && wxfn.IsFileReadable()) { 1162 wxCStrData csImageFileName = sImageFileName.c_str(); 1163 ptrImageFileName = (wxChar const *)csImageFileName; 1164 if (NULL != ptrImageFileName) { $? ". have wxChar file name" 1165 dke = pAppHelp->GetDkEncoding(); 1166 wxe = pAppHelp->GetWxEncoding(); 1167 res = dk4recwx_wxchar_to_dkchar( 1168 buf, DK4_SIZEOF(buf,dkChar), dke, ptrImageFileName, wxe, NULL 1169 ); 1170 if (0 != res) { $? ". have dkChar file name" 1171 pbif = dk4bif_open(buf, 1, NULL, NULL); 1172 if (NULL != pbif) { 1173 dk4_bif_dim_t w = dk4bif_get_width(pbif); 1174 dk4_bif_dim_t h = dk4bif_get_height(pbif); 1175 if ( 1176 ((dk4_im_t)0L < (dk4_im_t)w) 1177 && ((dk4_im_t)0L < (dk4_im_t)h) 1178 && ((dk4_im_t)(MAXIMGDIM) >= (dk4_im_t)w) 1179 && ((dk4_im_t)(MAXIMGDIM) >= (dk4_im_t)h) 1180 ) { 1181 spInputWidth->SetValue((int)w); 1182 spInputHeight->SetValue((int)h); 1183 success = true; 1184 } 1185#if TRACE_DEBUG 1186 else { $? "! dimensions out of range" 1187 } 1188#endif 1189 dk4bif_close(pbif); 1190 } 1191#if TRACE_DEBUG 1192 else { $? "! failed to open bif" 1193 } 1194#endif 1195 } 1196#if TRACE_DEBUG 1197 else { $? "! no dkChar file name" 1198 } 1199#endif 1200 } 1201#if TRACE_DEBUG 1202 else { $? "! no wxChar file name" 1203 } 1204#endif 1205 if (!(success)) { $? ". not yet succeeded" 1206 wxBitmapType t = bitmap_type_for_name(sImageFileName); 1207 if (wxBITMAP_TYPE_INVALID != t) { $? ". valid file type" 1208 wxBitmap bm(sImageFileName, t); 1209 if (bm.IsOk()) { 1210 int w = bm.GetWidth(); 1211 int h = bm.GetHeight(); 1212 if ((0 < w) && (0 < h)) { 1213 spInputWidth->SetValue(w); 1214 spInputHeight->SetValue(h); 1215 success = true; 1216 } 1217 else { $? "! dimensions out of range" 1218#if 0 1219 wxMessageBox( 1220 sTexts[44], sTexts[43], 1221 (wxOK | wxCENTRE | wxICON_ERROR) 1222 ); 1223#endif 1224 } 1225 } 1226 else { $? "! bitmap not ok" 1227#if 0 1228 wxMessageBox( 1229 sTexts[44],sTexts[43],(wxOK | wxCENTRE | wxICON_ERROR) 1230 ); 1231#endif 1232 } 1233 } 1234 else { $? "! invalid file suffix" 1235#if 0 1236 wxString s(sTexts[49]); 1237 s.Append(sImageFileName); 1238 s.Append(sTexts[50]); 1239 wxMessageBox( 1240 s, wxString(sTexts[43]), (wxOK | wxCENTRE | wxICON_ERROR) 1241 ); 1242#endif 1243 } 1244 } 1245 if (success) { 1246 Calculations(); 1247 } 1248 } 1249 else { 1250 if (!(wxfn.FileExists())) { $? "! no such file" 1251#if 0 1252 wxString s(sTexts[45]); 1253 s.Append(sImageFileName); 1254 s.Append(sTexts[46]); 1255 wxMessageBox( 1256 s, wxString(sTexts[43]), (wxOK | wxCENTRE | wxICON_ERROR) 1257 ); 1258#endif 1259 } 1260 else { 1261 if (!(wxfn.IsFileReadable())) { $? "! permissions" 1262#if 0 1263 wxString s(sTexts[47]); 1264 s.Append(sImageFileName); 1265 s.Append(sTexts[48]); 1266 wxMessageBox( 1267 s, wxString(sTexts[43]), (wxOK | wxCENTRE | wxICON_ERROR) 1268 ); 1269#endif 1270 } 1271 } 1272 } 1273 $? "- ProcessSpecifiedFileName" 1274} 1275 1276/* __CHANGE__ 008: Remove OnIdle if no idle processing required. 1277*/ 1278 1279/* __CHANGE__ 008: Remove the request for more events if not needed. 1280*/ 1281 1282/* __CHANGE__ 008: Decide about Skip() call. 1283 The function name is irritating: Skip() or Skip(true) will continue to 1284 process the event, calling default handlers. 1285 Skip(false) or handlers without Skip() will skip further processing of the 1286 event. 1287 1288 From the wxWidgets documenation: Skip() should be called for all 1289 non-command events to allow the default handling to take place. 1290 The command events are, however, normally not skipped as usually a single 1291 command such as a button click or menu item selection must only be 1292 processed by one handler. 1293 1294 So my recommendation is to have a Skip() call in the idle event handler. 1295*/ 1296 1297void 1298WximgszFrame::OnIdle(wxIdleEvent & event) 1299{ 1300 bool rqm = false; 1301 $? "+ WximgszFrame::OnIdle" 1302 /* __CHANGE__ 1303 */ 1304 if (bActive) { 1305 switch (cas.GetReaction()) { 1306 case Dk4WxAutostartController::REACTION_START : { 1307 cas.StartProcessing(); 1308 ProcessSpecifiedFileName(); 1309 cas.EndProcessing(); 1310 Refresh(); 1311 Update(); 1312 } break; 1313 } 1314 if (rqm) { event.RequestMore(); } 1315 } 1316 $? "- WximgszFrame::OnIdle" 1317 event.Skip(); 1318} 1319 1320 1321/* vim: set ai sw=4 ts=4 : */ 1322