#51 wip
authorKevin Lamonte <kevin.lamonte@gmail.com>
Wed, 21 Aug 2019 20:37:23 +0000 (15:37 -0500)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Wed, 21 Aug 2019 20:37:23 +0000 (15:37 -0500)
src/jexer/TSplitPane.java
src/jexer/TTerminalWidget.java
src/jexer/TWidget.java

index 5a65736add6ae1296860c7306295cc45bbfb8d09..a9d6cdb3f52760ac60c70dc1606a12b6d4f1eb6f 100644 (file)
@@ -587,15 +587,29 @@ public class TSplitPane extends TWidget {
         remove(false);
 
         if (keep == null) {
+            if (myParent instanceof TSplitPane) {
+                // TSplitPane has a left/right/top/bottom link to me
+                // somewhere, remove it.
+                ((TSplitPane) myParent).removeWidget(this);
+            }
+
             // Nothing is left of either pane.  Remove me and bail out.
             return null;
         }
 
-        keep.setParent(myParent, false);
-        keep.setDimensions(getX(), getY(), getWidth(), getHeight());
-        keep.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
-                getHeight()));
+        if (myParent instanceof TSplitPane) {
+            // TSplitPane has a left/right/top/bottom link to me
+            // somewhere, replace me with keep.
+            ((TSplitPane) myParent).replaceWidget(this, keep);
+        } else {
+            keep.setParent(myParent, false);
+            keep.setDimensions(getX(), getY(), getWidth(), getHeight());
+            keep.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, getWidth(),
+                    getHeight()));
+        }
 
+        // System.err.println("\nAfter removeSplit():\n" + myParent.toPrettyString());
+        
         return keep;
     }
 
index 7a93f4e7b32320c69ade2090049146e9200fdef0..39d761c64a1b2ae06fe2df6a5cbd1a143a8b4b5e 100644 (file)
@@ -384,6 +384,14 @@ public class TTerminalWidget extends TScrollableWidget
                 // Update the scroll bars
                 reflowData();
 
+                if (!isDrawable()) {
+                    // We lost the connection, onShellExit() called an action
+                    // that ultimately removed this widget from the UI
+                    // hierarchy, so no one cares if we update the display.
+                    // Bail out.
+                    return;
+                }
+
                 if ((scrollback == null) || emulator.isReading()) {
                     scrollback = copyBuffer(emulator.getScrollbackBuffer());
                     display = copyBuffer(emulator.getDisplayBuffer());
@@ -820,17 +828,19 @@ public class TTerminalWidget extends TScrollableWidget
     public void onShellExit() {
         TApplication app = getApplication();
         if (app != null) {
-            app.invokeLater(new Runnable() {
-                public void run() {
-                    if (closeAction != null) {
+            if (closeAction != null) {
+                // We have to put this action inside invokeLater() because it
+                // could be executed during draw() when syncing with ECMA48.
+                app.invokeLater(new Runnable() {
+                    public void run() {
                         closeAction.DO(TTerminalWidget.this);
                     }
-                    if (getApplication() != null) {
-                        getApplication().postEvent(new TMenuEvent(
-                            TMenu.MID_REPAINT));
-                    }
-                }
-            });
+                });
+            }
+            if (getApplication() != null) {
+                getApplication().postEvent(new TMenuEvent(
+                    TMenu.MID_REPAINT));
+            }
         }
     }
 
index 5d2612b3092e961d82ad8b6beea94ce93a20d15d..ba18989bfc43d38ea0549e42f5f20dfb8358e1ab 100644 (file)
@@ -1243,6 +1243,25 @@ public abstract class TWidget implements Comparable<TWidget> {
         return window.getApplication().getTheme();
     }
 
+    /**
+     * See if this widget can be drawn onto a screen.
+     *
+     * @return true if this widget is part of the hierarchy that can draw to
+     * a screen
+     */
+    public final boolean isDrawable() {
+        if ((window == null)
+            || (window.getScreen() == null)
+            || (parent == null)
+        ) {
+            return false;
+        }
+        if (parent == this) {
+            return true;
+        }
+        return (parent.isDrawable());
+    }
+
     /**
      * Draw my specific widget.  When called, the screen rectangle I draw
      * into is already setup (offset and clipping).
@@ -1255,7 +1274,7 @@ public abstract class TWidget implements Comparable<TWidget> {
      * Called by parent to render to TWindow.  Note package private access.
      */
     final void drawChildren() {
-        if (window == null) {
+        if (!isDrawable()) {
             return;
         }
 
@@ -1310,6 +1329,12 @@ public abstract class TWidget implements Comparable<TWidget> {
 
         // Draw me
         draw();
+        if (!isDrawable()) {
+            // An action taken by a draw method unhooked me from the UI.
+            // Bail out.
+            return;
+        }
+
         assert (visible == true);
 
         // Continue down the chain.  Draw the active child last so that it
@@ -1317,6 +1342,11 @@ public abstract class TWidget implements Comparable<TWidget> {
         for (TWidget widget: children) {
             if (widget.isVisible() && (widget != activeChild)) {
                 widget.drawChildren();
+                if (!isDrawable()) {
+                    // An action taken by a draw method unhooked me from the UI.
+                    // Bail out.
+                    return;
+                }
             }
         }
         if (activeChild != null) {