jhh6576 commited on
Commit
8b6151d
·
verified ·
1 Parent(s): 4d819c5

Update app_enhanced.py

Browse files
Files changed (1) hide show
  1. app_enhanced.py +39 -18
app_enhanced.py CHANGED
@@ -543,13 +543,14 @@ class EnhancedComicGenerator:
543
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
544
  .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; }
545
 
546
- /* <<< MODIFICATION START: New Robust Bordered Bubble CSS >>> */
547
  .speech-bubble.speech {
548
  background: var(--bubble-fill-color, white);
549
  color: var(--bubble-text-color, #333);
550
  border: 2px solid var(--bubble-border-color, #333);
551
  border-radius: 10px;
552
  padding: 0;
 
553
  }
554
 
555
  .speech-bubble.speech:after, .speech-bubble.speech:before {
@@ -557,16 +558,16 @@ class EnhancedComicGenerator:
557
  position: absolute;
558
  display: block;
559
  width: 0;
 
560
  }
561
 
562
- /* 4-WAY TAIL ROTATION CLASSES */
563
- /* BOTTOM */
564
  .speech-bubble.speech.tail-bottom:after {
565
  border-style: solid;
566
  border-width: 15px 15px 0 0;
567
  border-color: var(--bubble-fill-color, white) transparent transparent transparent;
568
  bottom: -15px;
569
- left: 50%;
570
  transform: translateX(-50%);
571
  z-index: 1;
572
  }
@@ -575,18 +576,18 @@ class EnhancedComicGenerator:
575
  border-width: 17px 17px 0 0;
576
  border-color: var(--bubble-border-color, #333) transparent transparent transparent;
577
  bottom: -19px;
578
- left: 50%;
579
  transform: translateX(-50%);
580
  z-index: 0;
581
  }
582
 
583
- /* TOP */
584
  .speech-bubble.speech.tail-top:after {
585
  border-style: solid;
586
  border-width: 0 15px 15px 0;
587
  border-color: transparent var(--bubble-fill-color, white) transparent transparent;
588
  top: -15px;
589
- left: 50%;
590
  transform: translateX(-50%) rotate(180deg);
591
  z-index: 1;
592
  }
@@ -595,17 +596,17 @@ class EnhancedComicGenerator:
595
  border-width: 0 17px 17px 0;
596
  border-color: transparent var(--bubble-border-color, #333) transparent transparent;
597
  top: -19px;
598
- left: 50%;
599
  transform: translateX(-50%) rotate(180deg);
600
  z-index: 0;
601
  }
602
 
603
- /* RIGHT */
604
- .speech-bubble.speech.tail-right:after {
605
  border-style: solid;
606
  border-width: 15px 15px 0 0;
607
  border-color: var(--bubble-fill-color, white) transparent transparent transparent;
608
- top: 50%;
609
  right: -15px;
610
  transform: translateY(-50%) rotate(90deg);
611
  z-index: 1;
@@ -614,18 +615,18 @@ class EnhancedComicGenerator:
614
  border-style: solid;
615
  border-width: 17px 17px 0 0;
616
  border-color: var(--bubble-border-color, #333) transparent transparent transparent;
617
- top: 50%;
618
  right: -19px;
619
  transform: translateY(-50%) rotate(90deg);
620
  z-index: 0;
621
  }
622
 
623
- /* LEFT */
624
  .speech-bubble.speech.tail-left:after {
625
  border-style: solid;
626
  border-width: 15px 15px 0 0;
627
  border-color: var(--bubble-fill-color, white) transparent transparent transparent;
628
- top: 50%;
629
  left: -15px;
630
  transform: translateY(-50%) rotate(-90deg);
631
  z-index: 1;
@@ -634,12 +635,11 @@ class EnhancedComicGenerator:
634
  border-style: solid;
635
  border-width: 17px 17px 0 0;
636
  border-color: var(--bubble-border-color, #333) transparent transparent transparent;
637
- top: 50%;
638
  left: -19px;
639
  transform: translateY(-50%) rotate(-90deg);
640
  z-index: 0;
641
  }
642
- /* <<< MODIFICATION END >>> */
643
 
644
  .speech-bubble.thought { background: white; border: 2px dashed #555; color: #333; border-radius: 50%; }
645
  .speech-bubble.reaction { background: #FFD700; border: 3px solid #E53935; color: #D32F2F; font-weight: 900; text-transform: uppercase; width: 180px; clip-path: polygon(0% 25%, 17% 21%, 17% 0%, 31% 16%, 50% 4%, 69% 16%, 83% 0%, 83% 21%, 100% 25%, 85% 45%, 95% 62%, 82% 79%, 100% 97%, 79% 89%, 60% 98%, 46% 82%, 27% 95%, 15% 78%, 5% 62%, 15% 45%); }
@@ -676,6 +676,9 @@ class EnhancedComicGenerator:
676
  .color-picker-grid div { text-align: center; }
677
  .color-picker-grid label { font-size: 11px; }
678
  .color-picker-grid input[type="color"] { height: 25px; padding: 2px; }
 
 
 
679
  </style>
680
  </head>
681
  <body>
@@ -711,8 +714,12 @@ class EnhancedComicGenerator:
711
  <button onclick="deleteBubble()" class="reset-button">🗑️ Delete Bubble</button>
712
  </div>
713
  <div class="control-group" id="tail-controls" style="display: none;">
714
- <label>Tail Controls</label>
715
- <button onclick="rotateBubbleTail()" class="secondary-button">🔄 Rotate Tail</button>
 
 
 
 
716
  </div>
717
  <div class="control-group">
718
  <label>Panel Tools (Select Panel):</label>
@@ -902,6 +909,11 @@ class EnhancedComicGenerator:
902
  alert("Tail rotation is only available for Speech and Thought bubbles.");
903
  }
904
  }
 
 
 
 
 
905
 
906
  function selectPanel(panel) {
907
  document.querySelectorAll('.panel.selected').forEach(p => p.classList.remove('selected'));
@@ -915,6 +927,7 @@ class EnhancedComicGenerator:
915
  currentlySelectedBubble = bubble;
916
  const bubbleControls = ['bubble-text-color', 'bubble-fill-color', 'bubble-type-select', 'font-select'];
917
  const tailControls = document.getElementById('tail-controls');
 
918
 
919
  if (currentlySelectedBubble) {
920
  currentlySelectedBubble.classList.add('selected');
@@ -934,6 +947,14 @@ class EnhancedComicGenerator:
934
  document.getElementById('bubble-type-select').value = currentlySelectedBubble.dataset.type || 'speech';
935
  document.getElementById('font-select').value = styles.fontFamily.split(',')[0].replace(/"/g, "").replace(/'/g, "").trim();
936
 
 
 
 
 
 
 
 
 
937
  document.getElementById('zoom-slider').disabled = true;
938
  bubbleControls.forEach(id => document.getElementById(id).disabled = false);
939
 
 
543
  .speech-bubble.selected { outline: 2px dashed #4CAF50; }
544
  .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; }
545
 
546
+ /* <<< FIXED BUBBLE CSS WITH DYNAMIC TAIL SLIDER >>> */
547
  .speech-bubble.speech {
548
  background: var(--bubble-fill-color, white);
549
  color: var(--bubble-text-color, #333);
550
  border: 2px solid var(--bubble-border-color, #333);
551
  border-radius: 10px;
552
  padding: 0;
553
+ --tail-pos: 50%; /* Default centered tail */
554
  }
555
 
556
  .speech-bubble.speech:after, .speech-bubble.speech:before {
 
558
  position: absolute;
559
  display: block;
560
  width: 0;
561
+ pointer-events: none;
562
  }
563
 
564
+ /* BOTTOM TAIL */
 
565
  .speech-bubble.speech.tail-bottom:after {
566
  border-style: solid;
567
  border-width: 15px 15px 0 0;
568
  border-color: var(--bubble-fill-color, white) transparent transparent transparent;
569
  bottom: -15px;
570
+ left: var(--tail-pos);
571
  transform: translateX(-50%);
572
  z-index: 1;
573
  }
 
576
  border-width: 17px 17px 0 0;
577
  border-color: var(--bubble-border-color, #333) transparent transparent transparent;
578
  bottom: -19px;
579
+ left: var(--tail-pos);
580
  transform: translateX(-50%);
581
  z-index: 0;
582
  }
583
 
584
+ /* TOP TAIL */
585
  .speech-bubble.speech.tail-top:after {
586
  border-style: solid;
587
  border-width: 0 15px 15px 0;
588
  border-color: transparent var(--bubble-fill-color, white) transparent transparent;
589
  top: -15px;
590
+ left: var(--tail-pos);
591
  transform: translateX(-50%) rotate(180deg);
592
  z-index: 1;
593
  }
 
596
  border-width: 0 17px 17px 0;
597
  border-color: transparent var(--bubble-border-color, #333) transparent transparent;
598
  top: -19px;
599
+ left: var(--tail-pos);
600
  transform: translateX(-50%) rotate(180deg);
601
  z-index: 0;
602
  }
603
 
604
+ /* RIGHT TAIL */
605
+ .speech-bubble.speech.tail-right:after {
606
  border-style: solid;
607
  border-width: 15px 15px 0 0;
608
  border-color: var(--bubble-fill-color, white) transparent transparent transparent;
609
+ top: var(--tail-pos);
610
  right: -15px;
611
  transform: translateY(-50%) rotate(90deg);
612
  z-index: 1;
 
615
  border-style: solid;
616
  border-width: 17px 17px 0 0;
617
  border-color: var(--bubble-border-color, #333) transparent transparent transparent;
618
+ top: var(--tail-pos);
619
  right: -19px;
620
  transform: translateY(-50%) rotate(90deg);
621
  z-index: 0;
622
  }
623
 
624
+ /* LEFT TAIL */
625
  .speech-bubble.speech.tail-left:after {
626
  border-style: solid;
627
  border-width: 15px 15px 0 0;
628
  border-color: var(--bubble-fill-color, white) transparent transparent transparent;
629
+ top: var(--tail-pos);
630
  left: -15px;
631
  transform: translateY(-50%) rotate(-90deg);
632
  z-index: 1;
 
635
  border-style: solid;
636
  border-width: 17px 17px 0 0;
637
  border-color: var(--bubble-border-color, #333) transparent transparent transparent;
638
+ top: var(--tail-pos);
639
  left: -19px;
640
  transform: translateY(-50%) rotate(-90deg);
641
  z-index: 0;
642
  }
 
643
 
644
  .speech-bubble.thought { background: white; border: 2px dashed #555; color: #333; border-radius: 50%; }
645
  .speech-bubble.reaction { background: #FFD700; border: 3px solid #E53935; color: #D32F2F; font-weight: 900; text-transform: uppercase; width: 180px; clip-path: polygon(0% 25%, 17% 21%, 17% 0%, 31% 16%, 50% 4%, 69% 16%, 83% 0%, 83% 21%, 100% 25%, 85% 45%, 95% 62%, 82% 79%, 100% 97%, 79% 89%, 60% 98%, 46% 82%, 27% 95%, 15% 78%, 5% 62%, 15% 45%); }
 
676
  .color-picker-grid div { text-align: center; }
677
  .color-picker-grid label { font-size: 11px; }
678
  .color-picker-grid input[type="color"] { height: 25px; padding: 2px; }
679
+
680
+ .slider-container { display: flex; align-items: center; gap: 5px; margin-top: 5px;}
681
+ .slider-container label { font-size: 11px; min-width: 50px;}
682
  </style>
683
  </head>
684
  <body>
 
714
  <button onclick="deleteBubble()" class="reset-button">🗑️ Delete Bubble</button>
715
  </div>
716
  <div class="control-group" id="tail-controls" style="display: none;">
717
+ <label>Tail Adjustment</label>
718
+ <button onclick="rotateBubbleTail()" class="secondary-button">🔄 Rotate Side</button>
719
+ <div class="slider-container">
720
+ <label>Pos:</label>
721
+ <input type="range" id="tail-slider" min="10" max="90" value="50" oninput="slideTail(this.value)">
722
+ </div>
723
  </div>
724
  <div class="control-group">
725
  <label>Panel Tools (Select Panel):</label>
 
909
  alert("Tail rotation is only available for Speech and Thought bubbles.");
910
  }
911
  }
912
+
913
+ function slideTail(value) {
914
+ if(!currentlySelectedBubble) return;
915
+ currentlySelectedBubble.style.setProperty('--tail-pos', value + '%');
916
+ }
917
 
918
  function selectPanel(panel) {
919
  document.querySelectorAll('.panel.selected').forEach(p => p.classList.remove('selected'));
 
927
  currentlySelectedBubble = bubble;
928
  const bubbleControls = ['bubble-text-color', 'bubble-fill-color', 'bubble-type-select', 'font-select'];
929
  const tailControls = document.getElementById('tail-controls');
930
+ const tailSlider = document.getElementById('tail-slider');
931
 
932
  if (currentlySelectedBubble) {
933
  currentlySelectedBubble.classList.add('selected');
 
947
  document.getElementById('bubble-type-select').value = currentlySelectedBubble.dataset.type || 'speech';
948
  document.getElementById('font-select').value = styles.fontFamily.split(',')[0].replace(/"/g, "").replace(/'/g, "").trim();
949
 
950
+ // Read current tail pos
951
+ const currentTailPos = styles.getPropertyValue('--tail-pos').trim();
952
+ if(currentTailPos.includes('%')) {
953
+ tailSlider.value = parseInt(currentTailPos);
954
+ } else {
955
+ tailSlider.value = 50;
956
+ }
957
+
958
  document.getElementById('zoom-slider').disabled = true;
959
  bubbleControls.forEach(id => document.getElementById(id).disabled = false);
960