jhh6576 commited on
Commit
955a8fd
·
verified ·
1 Parent(s): 9ce96e0

Update app_enhanced.py

Browse files
Files changed (1) hide show
  1. app_enhanced.py +41 -6
app_enhanced.py CHANGED
@@ -476,11 +476,9 @@ class EnhancedComicGenerator:
476
  os.makedirs(self.output_dir, exist_ok=True)
477
  pages_data = []
478
  for page in pages:
479
- # Ensure __dict__ is called on objects, not already-dicts from fallback
480
  panels = [p.__dict__ if hasattr(p, '__dict__') else p for p in page.panels]
481
- bubbles = [b.__dict__ if hasattr(b, '__dict__') else b for b in page.bubbles]
482
- pages_data.append({'panels': panels, 'bubbles': bubbles})
483
-
484
  with open(os.path.join(self.output_dir, 'pages.json'), 'w', encoding='utf-8') as f:
485
  json.dump(pages_data, f, indent=2)
486
  self._copy_template_files()
@@ -496,8 +494,11 @@ class EnhancedComicGenerator:
496
  <meta charset="UTF-8">
497
  <title>Comic Editor</title>
498
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
 
 
 
499
  <style>
500
- body { margin: 0; padding: 20px; background: #f0f0f0; font-family: Arial, sans-serif; }
501
  .comic-container { max-width: 1200px; margin: 0 auto; }
502
  .comic-page { background: white; width: 600px; height: 400px; box-shadow: 0 0 10px rgba(0,0,0,0.1); box-sizing: content-box; position: relative; overflow: hidden; border: 1px solid #333; padding: 10px; }
503
  .comic-grid { display: grid; grid-template-columns: 285px 285px; grid-template-rows: 185px 185px; gap: 10px; width: 100%; height: 100%; }
@@ -508,7 +509,7 @@ class EnhancedComicGenerator:
508
  .panel img { width: 100%; height: 100%; object-fit: cover; object-position: center; transition: transform 0.1s ease-out; }
509
  .panel img.pannable { cursor: grab; }
510
  .panel img.panning { cursor: grabbing; }
511
- .speech-bubble { position: absolute; display: flex; justify-content: center; align-items: center; width: auto; height: auto; min-width: 50px; max-width: 220px; min-height: 30px; box-sizing: border-box; padding: 8px; box-shadow: 2px 2px 5px rgba(0,0,0,0.3); z-index: 10; cursor: move; overflow: visible; font-size: 13px; font-weight: bold; text-align: center; }
512
  .bubble-text { padding: 2px; word-wrap: break-word; }
513
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
514
  .speech-bubble textarea { position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-sizing: border-box; border: 1px solid #4CAF50; background: rgba(255,255,255,0.95); font: inherit; text-align: center; resize: none; padding: 8px; z-index: 102; }
@@ -560,6 +561,12 @@ class EnhancedComicGenerator:
560
  <select id="bubble-type-select" onchange="changeBubbleType(this.value)" disabled>
561
  <option value="speech">Speech</option><option value="thought">Thought</option><option value="reaction">Reaction</option><option value="narration">Narration</option><option value="idea">Idea</option>
562
  </select>
 
 
 
 
 
 
563
  <div class="color-picker-grid">
564
  <div>
565
  <label for="bubble-text-color">Text</label>
@@ -572,6 +579,7 @@ class EnhancedComicGenerator:
572
  </div>
573
  <button onclick="rotateBubbleTail()" class="secondary-button">🔄 Rotate Tail</button>
574
  <button onclick="addBubbleToPanel()" class="action-button">💬 Add Bubble</button>
 
575
  </div>
576
  <div class="control-group">
577
  <label>Panel Tools (Select Panel):</label>
@@ -726,6 +734,11 @@ class EnhancedComicGenerator:
726
  applyBubbleType(currentlySelectedBubble, type);
727
  }
728
 
 
 
 
 
 
729
  function rotateBubbleTail() {
730
  if (!currentlySelectedBubble) { alert("Please select a bubble first."); return; }
731
  const isFlippedH = currentlySelectedBubble.classList.contains('flipped');
@@ -749,6 +762,7 @@ class EnhancedComicGenerator:
749
  document.getElementById('bubble-type-select').disabled = true;
750
  document.getElementById('bubble-text-color').disabled = true;
751
  document.getElementById('bubble-fill-color').disabled = true;
 
752
  }
753
 
754
  function selectBubble(bubble) {
@@ -757,6 +771,7 @@ class EnhancedComicGenerator:
757
  const textColorPicker = document.getElementById('bubble-text-color');
758
  const fillColorPicker = document.getElementById('bubble-fill-color');
759
  const typeSelect = document.getElementById('bubble-type-select');
 
760
 
761
  if (currentlySelectedBubble) {
762
  currentlySelectedBubble.classList.add('selected');
@@ -768,10 +783,18 @@ class EnhancedComicGenerator:
768
  fillColorPicker.value = rgbToHex(styles.backgroundColor);
769
 
770
  typeSelect.value = currentlySelectedBubble.dataset.type || 'speech';
 
 
771
  document.getElementById('zoom-slider').disabled = true;
772
  textColorPicker.disabled = false;
773
  fillColorPicker.disabled = false;
774
  typeSelect.disabled = false;
 
 
 
 
 
 
775
  }
776
  }
777
 
@@ -812,6 +835,18 @@ class EnhancedComicGenerator:
812
 
813
  function stopDrag() { draggedBubble = null; }
814
 
 
 
 
 
 
 
 
 
 
 
 
 
815
  function clearSavedState() {
816
  if (confirm("Reset all edits?")) {
817
  localStorage.removeItem('comicEditorState');
 
476
  os.makedirs(self.output_dir, exist_ok=True)
477
  pages_data = []
478
  for page in pages:
 
479
  panels = [p.__dict__ if hasattr(p, '__dict__') else p for p in page.panels]
480
+ bubbles_data = [b.__dict__ if hasattr(b, '__dict__') else b for b in page.bubbles]
481
+ pages_data.append({'panels': panels, 'bubbles': bubbles_data})
 
482
  with open(os.path.join(self.output_dir, 'pages.json'), 'w', encoding='utf-8') as f:
483
  json.dump(pages_data, f, indent=2)
484
  self._copy_template_files()
 
494
  <meta charset="UTF-8">
495
  <title>Comic Editor</title>
496
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
497
+ <link rel="preconnect" href="https://fonts.googleapis.com">
498
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
499
+ <link href="https://fonts.googleapis.com/css2?family=Bangers&family=Comic+Neue:wght@700&family=Gloria+Hallelujah&family=Lato&display=swap" rel="stylesheet">
500
  <style>
501
+ body { margin: 0; padding: 20px; background: #f0f0f0; font-family: 'Lato', sans-serif; }
502
  .comic-container { max-width: 1200px; margin: 0 auto; }
503
  .comic-page { background: white; width: 600px; height: 400px; box-shadow: 0 0 10px rgba(0,0,0,0.1); box-sizing: content-box; position: relative; overflow: hidden; border: 1px solid #333; padding: 10px; }
504
  .comic-grid { display: grid; grid-template-columns: 285px 285px; grid-template-rows: 185px 185px; gap: 10px; width: 100%; height: 100%; }
 
509
  .panel img { width: 100%; height: 100%; object-fit: cover; object-position: center; transition: transform 0.1s ease-out; }
510
  .panel img.pannable { cursor: grab; }
511
  .panel img.panning { cursor: grabbing; }
512
+ .speech-bubble { font-family: 'Comic Neue', cursive; position: absolute; display: flex; justify-content: center; align-items: center; width: auto; height: auto; min-width: 50px; max-width: 220px; min-height: 30px; box-sizing: border-box; padding: 8px; box-shadow: 2px 2px 5px rgba(0,0,0,0.3); z-index: 10; cursor: move; overflow: visible; font-size: 13px; font-weight: bold; text-align: center; }
513
  .bubble-text { padding: 2px; word-wrap: break-word; }
514
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
515
  .speech-bubble textarea { position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-sizing: border-box; border: 1px solid #4CAF50; background: rgba(255,255,255,0.95); font: inherit; text-align: center; resize: none; padding: 8px; z-index: 102; }
 
561
  <select id="bubble-type-select" onchange="changeBubbleType(this.value)" disabled>
562
  <option value="speech">Speech</option><option value="thought">Thought</option><option value="reaction">Reaction</option><option value="narration">Narration</option><option value="idea">Idea</option>
563
  </select>
564
+ <select id="font-select" onchange="changeFont(this.value)" disabled>
565
+ <option value="'Comic Neue', cursive">Comic Neue</option>
566
+ <option value="'Bangers', cursive">Bangers</option>
567
+ <option value="'Gloria Hallelujah', cursive">Gloria</option>
568
+ <option value="'Lato', sans-serif">Lato</option>
569
+ </select>
570
  <div class="color-picker-grid">
571
  <div>
572
  <label for="bubble-text-color">Text</label>
 
579
  </div>
580
  <button onclick="rotateBubbleTail()" class="secondary-button">🔄 Rotate Tail</button>
581
  <button onclick="addBubbleToPanel()" class="action-button">💬 Add Bubble</button>
582
+ <button onclick="deleteBubble()" class="reset-button">🗑️ Delete Bubble</button>
583
  </div>
584
  <div class="control-group">
585
  <label>Panel Tools (Select Panel):</label>
 
734
  applyBubbleType(currentlySelectedBubble, type);
735
  }
736
 
737
+ function changeFont(font) {
738
+ if (!currentlySelectedBubble) return;
739
+ currentlySelectedBubble.style.fontFamily = font;
740
+ }
741
+
742
  function rotateBubbleTail() {
743
  if (!currentlySelectedBubble) { alert("Please select a bubble first."); return; }
744
  const isFlippedH = currentlySelectedBubble.classList.contains('flipped');
 
762
  document.getElementById('bubble-type-select').disabled = true;
763
  document.getElementById('bubble-text-color').disabled = true;
764
  document.getElementById('bubble-fill-color').disabled = true;
765
+ document.getElementById('font-select').disabled = true;
766
  }
767
 
768
  function selectBubble(bubble) {
 
771
  const textColorPicker = document.getElementById('bubble-text-color');
772
  const fillColorPicker = document.getElementById('bubble-fill-color');
773
  const typeSelect = document.getElementById('bubble-type-select');
774
+ const fontSelect = document.getElementById('font-select');
775
 
776
  if (currentlySelectedBubble) {
777
  currentlySelectedBubble.classList.add('selected');
 
783
  fillColorPicker.value = rgbToHex(styles.backgroundColor);
784
 
785
  typeSelect.value = currentlySelectedBubble.dataset.type || 'speech';
786
+ fontSelect.value = styles.fontFamily.split(',')[0].replace(/"/g, "'");
787
+
788
  document.getElementById('zoom-slider').disabled = true;
789
  textColorPicker.disabled = false;
790
  fillColorPicker.disabled = false;
791
  typeSelect.disabled = false;
792
+ fontSelect.disabled = false;
793
+ } else {
794
+ textColorPicker.disabled = true;
795
+ fillColorPicker.disabled = true;
796
+ typeSelect.disabled = true;
797
+ fontSelect.disabled = true;
798
  }
799
  }
800
 
 
835
 
836
  function stopDrag() { draggedBubble = null; }
837
 
838
+ function deleteBubble() {
839
+ if (!currentlySelectedBubble) {
840
+ alert("Please select a bubble to delete.");
841
+ return;
842
+ }
843
+ if (confirm("Are you sure you want to delete this bubble?")) {
844
+ currentlySelectedBubble.remove();
845
+ currentlySelectedBubble = null;
846
+ selectBubble(null); // Deselect and disable controls
847
+ }
848
+ }
849
+
850
  function clearSavedState() {
851
  if (confirm("Reset all edits?")) {
852
  localStorage.removeItem('comicEditorState');