1: <?php
2: 3: 4: 5: 6:
7:
8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
35: class QImageBrowserNav extends QPanel {
36: protected $btnFirst;
37: protected $btnPrev;
38: protected $btnNext;
39: protected $btnLast;
40:
41: public function __construct($objParentObject, $strControlId = null) {
42:
43: try {
44: parent::__construct($objParentObject, $strControlId);
45: } catch (QCallerException $objExc) {
46: $objExc->IncrementOffset();
47: throw $objExc;
48: }
49: $this->AutoRenderChildren = true;
50:
51: $this->btnFirst = new QButton($this);
52: $this->btnFirst->Text = QApplication::Translate('First');
53: $this->btnFirst->Enabled = false;
54: $this->btnFirst->CssClass = 'button ib_nav_button ib_nav_button_first';
55:
56: $this->btnPrev = new QButton($this);
57: $this->btnPrev->Text = QApplication::Translate('Previous');
58: $this->btnPrev->Enabled = false;
59: $this->btnPrev->CssClass = 'button ib_nav_button ib_nav_button_prev';
60:
61: $this->btnNext = new QButton($this);
62: $this->btnNext->Text = QApplication::Translate('Next');
63: $this->btnNext->Enabled = false;
64: $this->btnNext->CssClass = 'button ib_nav_button ib_nav_button_next';
65:
66: $this->btnLast = new QButton($this);
67: $this->btnLast->Text = QApplication::Translate('Last');
68: $this->btnLast->Enabled = false;
69: $this->btnLast->CssClass = 'button ib_nav_button ib_nav_button_last';
70:
71: $this->setButtonActions();
72: }
73:
74: protected function setButtonActions(array $arrButtons = null) {
75:
76: $objImageBrowser = $this->ParentControl;
77: while ( !($objImageBrowser instanceof QImageBrowserBase) ) {
78: $objImageBrowser = $objImageBrowser->ParentControl;
79: if (is_null($objImageBrowser) || $objImageBrowser instanceof QForm) {
80: throw new QCallerException("QImageBrowserNav must be inside a QImageBrowser");
81: }
82: }
83: if (!$arrButtons) {
84: $arrButtons = array(
85: "btnFirst_Click" => $this->btnFirst,
86: "btnPrev_Click" => $this->btnPrev,
87: "btnNext_Click" => $this->btnNext,
88: "btnLast_Click" => $this->btnLast);
89: }
90:
91: foreach ($arrButtons as $strActionCalback => $objButton) {
92: $objButton->RemoveAllActions(QClickEvent::EventName);
93: $objButton->AddAction(new QClickEvent(), new QAjaxControlAction($objImageBrowser, $strActionCalback));
94: }
95: }
96:
97: public function BackButtonsEnabled($blnEnable) {
98: $this->btnFirst->Enabled = $blnEnable;
99: $this->btnPrev->Enabled = $blnEnable;
100: }
101:
102: public function ForwardButtonsEnabled($blnEnable) {
103: $this->btnNext->Enabled = $blnEnable;
104: $this->btnLast->Enabled = $blnEnable;
105: }
106:
107: public function __get($strName) {
108: switch ($strName) {
109: case "FirstButton": return $this->btnFirst;
110: case "PrevButton": return $this->btnPrev;
111: case "NextButton": return $this->btnNext;
112: case "LastButton": return $this->btnLast;
113: default:
114: try {
115: return parent::__get($strName);
116: } catch (QCallerException $objExc) {
117: $objExc->IncrementOffset();
118: throw $objExc;
119: }
120: }
121: }
122:
123: public function __set($strName, $mixValue) {
124: $this->blnModified = true;
125:
126: switch ($strName) {
127: case "FirstButton":
128: try {
129: $this->RemoveChildControl($this->btnFirst->ControlId, true);
130: $this->btnFirst = QType::Cast($mixValue, 'QControl');
131: $this->setButtonActions(array("btnFirst_Click" => $this->btnFirst));
132: break;
133: } catch (QInvalidCastException $objExc) {
134: $objExc->IncrementOffset();
135: throw $objExc;
136: }
137:
138: case "PrevButton":
139: try {
140: $this->RemoveChildControl($this->btnPrev->ControlId, true);
141: $this->btnPrev = QType::Cast($mixValue, 'QControl');
142: $this->setButtonActions(array("btnPrev_Click" => $this->btnPrev));
143: break;
144: } catch (QInvalidCastException $objExc) {
145: $objExc->IncrementOffset();
146: throw $objExc;
147: }
148:
149: case "NextButton":
150: try {
151: $this->RemoveChildControl($this->btnNext->ControlId, true);
152: $this->btnNext = QType::Cast($mixValue, 'QControl');
153: $this->setButtonActions(array("btnNext_Click" => $this->btnNext));
154: break;
155: } catch (QInvalidCastException $objExc) {
156: $objExc->IncrementOffset();
157: throw $objExc;
158: }
159:
160: case "LastButton":
161: try {
162: $this->RemoveChildControl($this->btnLast->ControlId, true);
163: $this->btnLast = QType::Cast($mixValue, 'QControl');
164: $this->setButtonActions(array("btnLast_Click" => $this->btnLast));
165: break;
166: } catch (QInvalidCastException $objExc) {
167: $objExc->IncrementOffset();
168: throw $objExc;
169: }
170:
171: default:
172: try {
173: parent::__set($strName, $mixValue);
174: } catch (QCallerException $objExc) {
175: $objExc->IncrementOffset();
176: throw $objExc;
177: }
178: break;
179: }
180: }
181: }
182:
183: 184: 185:
186: class QImageBrowserThumbnails extends QPanel {
187: public function __construct($objParentObject, $strControlId = null) {
188:
189: try {
190: parent::__construct($objParentObject, $strControlId);
191: } catch (QCallerException $objExc) {
192: $objExc->IncrementOffset();
193: throw $objExc;
194: }
195: $this->AutoRenderChildren = true;
196: }
197:
198: public function reload() {
199: $this->RemoveChildControls(true);
200: $img = null;
201:
202: $objImageBrowser = $this->ParentControl;
203: while ( !($objImageBrowser instanceof QImageBrowserBase) ) {
204: $objImageBrowser = $objImageBrowser->ParentControl;
205: if (is_null($objImageBrowser) || $objImageBrowser instanceof QForm) {
206: throw new QCallerException("QImageBrowserThumbnails must be inside a QImageBrowser");
207: }
208: }
209: $iEnd = $objImageBrowser->ImageCount();
210: for ($i = 0; $i < $iEnd; ++$i) {
211: $strImagePath = $objImageBrowser->ThumbnailImagePath($i);
212: $img = new QImageControl($this);
213: $img->CssClass = 'ib_thm_image';
214: $img->ImagePath = $strImagePath;
215: $img->AlternateText = $strImagePath;
216: $img->ActionParameter = $i;
217:
218:
219:
220: $img->CacheFolder = __IMAGE_CACHE_ASSETS__;
221:
222: $img->AddAction(new QClickEvent(), new QAjaxControlAction($objImageBrowser, "imgThm_Click"));
223: }
224: if ($img) {
225: $img->CssClass = 'ib_thm_image ib_thm_image_last';
226: $this->Text = '';
227: } else {
228: $this->Text = QApplication::Translate('No thumbnails');
229: }
230: }
231: }
232:
233: 234: 235: 236: 237: 238: 239: 240: 241:
242: abstract class QImageBrowserBase extends QPanel {
243: protected $intCurrentImage;
244: protected $imgMainImage;
245: protected $txtCaption;
246: protected $btnSave;
247: protected $ibnNavigation1;
248: protected $ibnNavigation2;
249: protected $ibtThumbnails;
250:
251: 252: 253: 254: 255: 256: 257:
258: public function __construct($objParentObject, $blnReadOnlyCaption = true, $blnTwoNavBars = false, $blnThumbnails = true, $strControlId = null) {
259:
260: try {
261: parent::__construct($objParentObject, $strControlId);
262: } catch (QCallerException $objExc) {
263: $objExc->IncrementOffset();
264: throw $objExc;
265: }
266: $this->intCurrentImage = null;
267:
268:
269: $this->imgMainImage = new QImageControl($this);
270: $this->imgMainImage->CssClass = 'ib_main_image';
271: $this->imgMainImage->ImagePath = $this->invalidImagePath();
272:
273:
274:
275: $this->imgMainImage->CacheFolder = __IMAGE_CACHE_ASSETS__;
276:
277:
278: $this->txtCaption = new QTextBox($this);
279: $this->txtCaption->Name = 'Caption';
280: $this->txtCaption->TextMode = QTextMode::MultiLine;
281: $this->txtCaption->Rows = 2;
282: $this->txtCaption->Enabled = false;
283: if ($blnReadOnlyCaption) {
284: $this->txtCaption->CssClass = 'textbox ib_caption ib_caption_readonly';
285: $this->txtCaption->ReadOnly = true;
286: } else {
287: $this->txtCaption->CssClass = 'textbox ib_caption';
288: $this->txtCaption->AddAction(new QChangeEvent(), new QAjaxControlAction($this, "txtCaption_Change"));
289:
290: $this->btnSave = new QButton($this);
291: $this->btnSave->Text = QApplication::Translate('Save');
292: $this->btnSave->Enabled = false;
293: $this->btnSave->AddAction(new QClickEvent(), new QAjaxControlAction($this, "btnSave_Click"));
294: }
295:
296:
297: $this->ibnNavigation1 = new QImageBrowserNav($this);
298: $this->ibnNavigation1->CssClass = 'ib_nav ib_nav1';
299: if ($blnTwoNavBars) {
300: $this->ibnNavigation2 = new QImageBrowserNav($this);
301: $this->ibnNavigation2->CssClass = 'ib_nav ib_nav2';
302: }
303:
304:
305: if ($blnThumbnails) {
306: $this->ibtThumbnails = new QImageBrowserThumbnails($this);
307: $this->ibtThumbnails->CssClass = 'ib_thm';
308: }
309: }
310:
311: protected function reload() {
312: $this->ibtThumbnails->reload();
313: $this->intCurrentImage = 0;
314: $this->setMainImage($this->intCurrentImage);
315: }
316:
317: protected function setMainImage($intIdx) {
318: $intCount = $this->ImageCount();
319: $blnBackButtonsEnabled = $intCount > 1 && $intIdx > 0;
320: $blnForwardButtonsEnabled = $intCount > 1 && $intIdx+1 < $intCount;
321: $this->ibnNavigation1->BackButtonsEnabled($blnBackButtonsEnabled);
322: if ($this->ibnNavigation2) {
323: $this->ibnNavigation2->BackButtonsEnabled($blnBackButtonsEnabled);
324: }
325: $this->ibnNavigation1->ForwardButtonsEnabled($blnForwardButtonsEnabled);
326: if ($this->ibnNavigation2) {
327: $this->ibnNavigation2->ForwardButtonsEnabled($blnForwardButtonsEnabled);
328: }
329: if ($this->btnSave) {
330: $this->btnSave->Enabled = false;
331: }
332: if ($intIdx < 0 || $intIdx >= $intCount) {
333: $this->intCurrentImage = null;
334: $this->imgMainImage->ImagePath = $this->invalidImagePath();
335: $this->txtCaption->Enabled = false;
336: $this->txtCaption->Text = '';
337: return;
338: }
339: $this->txtCaption->Enabled = true;
340: $strImagePath = $this->ImagePath($intIdx);
341: $this->imgMainImage->ImagePath = $strImagePath;
342: if ($this->ibtThumbnails) {
343: foreach ($this->ibtThumbnails->GetChildControls() as $ctrl) {
344: if ($ctrl instanceof QImageControl) {
345: if ($ctrl->ImagePath == $strImagePath) {
346: $ctrl->AddCssClass($this->selectThumbnailCssClass());
347: } else {
348: $ctrl->RemoveCssClass($this->selectThumbnailCssClass());
349: }
350: }
351: }
352: }
353: $this->intCurrentImage = $intIdx;
354: $this->txtCaption->Text = $this->loadCaption($intIdx);
355: }
356:
357: public function btnFirst_Click($strFormId, $strControlId, $strParameter) {
358: $this->setMainImage(0);
359: }
360:
361: public function btnNext_Click($strFormId, $strControlId, $strParameter) {
362: if (!is_null($this->intCurrentImage)) {
363: $this->setMainImage($this->intCurrentImage + 1);
364: }
365: }
366:
367: public function btnPrev_Click($strFormId, $strControlId, $strParameter) {
368: if (!is_null($this->intCurrentImage)) {
369: $this->setMainImage($this->intCurrentImage - 1);
370: }
371: }
372:
373: public function btnLast_Click($strFormId, $strControlId, $strParameter) {
374: $this->setMainImage($this->ImageCount()-1);
375: }
376:
377: public function imgThm_Click($strFormId, $strControlId, $strParameter) {
378: $this->setMainImage($strParameter);
379: }
380:
381: public function btnSave_Click($strFormId, $strControlId, $strParameter) {
382: $this->saveCaption($this->intCurrentImage, $this->txtCaption->Text);
383: if ($this->btnSave) {
384: $this->btnSave->Enabled = false;
385: }
386: }
387:
388: public function txtCaption_Change($strFormId, $strControlId, $strParameter) {
389: if ($this->btnSave) {
390: $this->btnSave->Enabled = !is_null($this->intCurrentImage);
391: }
392: }
393:
394:
395:
396:
397:
398: 399: 400: 401: 402:
403: abstract public function ImageCount();
404:
405: 406: 407: 408: 409: 410:
411: abstract public function ImagePath($intIdx);
412:
413: 414: 415: 416: 417: 418: 419:
420: abstract public function ThumbnailImagePath($intIdx);
421:
422: 423: 424: 425: 426: 427:
428: abstract protected function loadCaption($intIdx);
429:
430:
431: 432: 433: 434: 435:
436: abstract protected function saveCaption($intIdx, $strCaption);
437:
438:
439: 440: 441: 442: 443: 444:
445: protected function selectThumbnailCssClass() {
446: return 'ib_thm_selected';
447: }
448:
449: 450: 451: 452: 453: 454:
455: protected function invalidImagePath() {
456: return __DOCROOT__ . __IMAGE_ASSETS__ . '/file_asset_blank.png';
457: }
458:
459: public function __get($strName) {
460: switch ($strName) {
461: case "MainImage": return $this->imgMainImage;
462: case "Caption": return $this->txtCaption;
463: case "SaveButton": return $this->btnSave;
464: case "Navigation1": return $this->ibnNavigation1;
465: case "Navigation2": return $this->ibnNavigation2;
466: case "Thumbnails": return $this->ibtThumbnails;
467: default:
468: try {
469: return parent::__get($strName);
470: } catch (QCallerException $objExc) {
471: $objExc->IncrementOffset();
472: throw $objExc;
473: }
474: }
475: }
476:
477: public function __set($strName, $mixValue) {
478: $this->blnModified = true;
479:
480: switch ($strName) {
481: case "Navigation1":
482: try {
483: if ($this->ibnNavigation1)
484: $this->RemoveChildControl($this->ibnNavigation1->ControlId, true);
485: $this->ibnNavigation1 = QType::Cast($mixValue, 'QImageBrowserNav');
486: break;
487: } catch (QInvalidCastException $objExc) {
488: $objExc->IncrementOffset();
489: throw $objExc;
490: }
491:
492: case "Navigation2":
493: try {
494: if ($this->ibnNavigation2)
495: $this->RemoveChildControl($this->ibnNavigation2->ControlId, true);
496: $this->ibnNavigation2 = QType::Cast($mixValue, 'QImageBrowserNav');
497: break;
498: } catch (QInvalidCastException $objExc) {
499: $objExc->IncrementOffset();
500: throw $objExc;
501: }
502:
503: case "Thumbnails":
504: try {
505: if ($this->ibtThumbnails)
506: $this->RemoveChildControl($this->ibtThumbnails->ControlId, true);
507: $this->ibtThumbnails = QType::Cast($mixValue, 'QImageBrowserThumbnails');
508: break;
509: } catch (QInvalidCastException $objExc) {
510: $objExc->IncrementOffset();
511: throw $objExc;
512: }
513:
514: case "Caption":
515: try {
516: if ($this->txtCaption)
517: $this->RemoveChildControl($this->txtCaption->ControlId, true);
518: $this->txtCaption = QType::Cast($mixValue, 'QControl');
519: break;
520: } catch (QInvalidCastException $objExc) {
521: $objExc->IncrementOffset();
522: throw $objExc;
523: }
524:
525: case "SaveButton":
526: try {
527: if ($this->btnSave) {
528: $this->btnSave->RemoveAllActions(QClickEvent::EventName);
529: $this->RemoveChildControl($this->btnSave->ControlId, true);
530: }
531: $this->btnSave = QType::Cast($mixValue, 'QControl');
532: $this->btnSave->AddAction(new QClickEvent(), new QAjaxControlAction($this, "btnSave_Click"));
533: break;
534: } catch (QInvalidCastException $objExc) {
535: $objExc->IncrementOffset();
536: throw $objExc;
537: }
538:
539: default:
540: try {
541: parent::__set($strName, $mixValue);
542: } catch (QCallerException $objExc) {
543: $objExc->IncrementOffset();
544: throw $objExc;
545: }
546: break;
547: }
548: }
549: }
550:
551: 552: 553: 554: 555: 556: 557: 558: 559: 560:
561: class QImageBrowser extends QImageBrowserBase {
562: protected $arrImagePaths;
563:
564: public function LoadImagesFromDirectory($strDir, $strPattern) {
565: if (!is_dir($strDir)) {
566: throw new QCallerException("$strDir is not a directory");
567: }
568:
569: $dh = opendir($strDir);
570: if ($dh === false) {
571: throw new QCallerException("Could not open directory $strDir");
572: }
573: $this->arrImagePaths = array();
574: while ($strFile = readdir($dh)) {
575: if ("." == $strFile || ".." == $strFile) {
576: continue;
577: }
578: if (preg_match($strPattern, $strFile) > 0) {
579: $this->arrImagePaths[] = $strDir.'/'.$strFile;
580: }
581: }
582: closedir($dh);
583: $this->reload();
584: }
585:
586: public function ImageCount() {
587: if (!$this->arrImagePaths) return 0;
588: return count($this->arrImagePaths);
589: }
590:
591: public function ImagePath($intIdx) {
592: return $this->arrImagePaths[$intIdx];
593: }
594:
595: public function ThumbnailImagePath($intIdx) {
596: return $this->ImagePath($intIdx);
597: }
598:
599: protected function captionFileName($intIdx) {
600: $strImagePath = $this->ImagePath($intIdx);
601: return $strImagePath.'.txt';
602: }
603:
604: protected function loadCaption($intIdx) {
605: $strCaptionFile = $this->captionFileName($intIdx);
606: if (!file_exists($strCaptionFile)) {
607:
608: return '';
609: }
610: if (false === ($strCaption = file_get_contents($strCaptionFile))) {
611:
612: return '';
613: }
614: return $strCaption;
615: }
616:
617: protected function saveCaption($intIdx, $strCaption) {
618: $strCaptionFile = $this->captionFileName($intIdx);
619: file_put_contents($strCaptionFile, $strCaption, LOCK_EX);
620: }
621:
622: public function __get($strName) {
623: switch ($strName) {
624: case "ImagePaths": return $this->arrImagePaths;
625: default:
626: try {
627: return parent::__get($strName);
628: } catch (QCallerException $objExc) {
629: $objExc->IncrementOffset();
630: throw $objExc;
631: }
632: }
633: }
634: public function __set($strName, $mixValue) {
635: $this->blnModified = true;
636:
637: switch ($strName) {
638: case "ImagePaths":
639: try {
640: $this->arrImagePaths = QType::Cast($mixValue, QType::ArrayType);
641: $this->reload();
642: break;
643: } catch (QInvalidCastException $objExc) {
644: $objExc->IncrementOffset();
645: throw $objExc;
646: }
647:
648: default:
649: try {
650: parent::__set($strName, $mixValue);
651: } catch (QCallerException $objExc) {
652: $objExc->IncrementOffset();
653: throw $objExc;
654: }
655: break;
656: }
657: }
658: }