Перезаписать основную оболочку приложения Eclipse RCP - PullRequest
0 голосов
/ 03 мая 2018

Я пытался «переопределить» главное окно моего приложения Eclipse RCP, чтобы отобразить красную границу «записи», когда в приложении включена функция записи экрана.

private boolean isActive;

private final ProgressMonitorDialog monitor;

private PaintListener paintListener;
private final int recordingFrameThickness = 5;  

public boolean toggle() {
  isActive = !isActive;

  try {
    // New state
    if (isActive) {
      monitor.run(true, false, new BackupExecutionBeginRecording(Display.getCurrent()));
      addRecordingFrame(Display.getCurrent().getActiveShell());
    }
    else {
      monitor.run(true, false, new BackupExecutionAfterRecording());
      removeRecoringFrame(Display.getCurrent().getActiveShell());
    }
  }
  catch (InvocationTargetException e) {
    System.err.println("Couldn't start backup task. Error: " + e.getMessage());
  }
  catch (InterruptedException e) {
    System.err.println("Backup thread was interrupted. Error: " + e.getMessage());
  }

  return isActive;
}

private void addRecordingFrame(Shell shell) {
  paintListener = new PaintListener() {

    @Override
    public void paintControl(PaintEvent e) {
      Rectangle clientArea = shell.getClientArea();
      e.gc.setLineWidth(recordingFrameThickness);
      e.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
      e.gc.drawRectangle(clientArea);
    }
  };

  shell.addPaintListener(paintListener);
}

private void removeRecoringFrame(Shell shell) {
  shell.removePaintListener(paintListener);
}

Как видите, подход, который я использовал, заключается в том, чтобы подождать, пока не будет нарисовано главное окно приложения, и добавить прямоугольник. Теоретически, после каждого изменения размера или положения окна наложенная красная рамка должна отображаться снова. Но похоже, что PaintEvent не вызывается основной оболочкой приложения.

Есть ли другой способ нарисовать что-либо на существующем макете приложения, не блокируя взаимодействие с элементами управления ниже?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Используя приведенное ниже решение, я смог нарисовать красную рамку вокруг моей основной оболочки, которая «следует» за любым перемещением и изменением размеров оболочки. Остается большой недостаток: красная граница, кажется, имеет внешнюю границу (созданную регионом?), Которая перекрывает маркеры, используемые для изменения размера оболочки. В связи с этим изменение размера оболочки возможно только в том случае, если красная рамка не отображается (то есть оболочка не имеет фокуса).

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Shell;

public class RecordingFrame {

    private Shell baseShell;
    private Shell overlayShell;

    private ControlListener controlListener;
    private ShellListener shellListener;
    private PaintListener paintListener;

    private Rectangle outerRect;
    private Rectangle innerRect;
    private Region region;

    private int lineWidth = 10;
    private Color color;

    public RecordingFrame(Shell baseShell) {
        this.baseShell = baseShell;

        // Set up new shell
        overlayShell = new Shell(baseShell, SWT.BORDER | SWT.NO_TRIM | SWT.ON_TOP);
        overlayShell.setVisible(true);

        // Initialize objects
        outerRect = new Rectangle(0, 0, 0, 0);
        innerRect = new Rectangle(0, 0, 0, 0);
        region = new Region();

        color = new Color(baseShell.getDisplay(), 255, 0, 0);

        // First drawing of frame
        redraw();

        // Configure listeners
        initListeners();

        // Add listeners to shells
        baseShell.addControlListener(controlListener);
        baseShell.addShellListener(shellListener);
        overlayShell.addPaintListener(paintListener);
    }

    public void dispose() {
      // Remove all listeners
      overlayShell.removePaintListener(paintListener);
        baseShell.removeControlListener(controlListener);
        baseShell.removeShellListener(shellListener);

        if (!overlayShell.isDisposed())
            overlayShell.dispose();
    }

    private void redraw() {

      // Get bounds of base shell
        overlayShell.setBounds(baseShell.getBounds());

        // Calculate outer rectangle
        outerRect.height = overlayShell.getBounds().height;
        outerRect.width = overlayShell.getBounds().width;
        outerRect.x = 0;
        outerRect.y = 0;

        // Calculate inner rectangle
        innerRect.height = outerRect.height - 2 * lineWidth;
        innerRect.width = outerRect.width - 2 * lineWidth;
        innerRect.x = 0 + lineWidth;
        innerRect.y = 0 + lineWidth;

        // Create a new region which is the outer shell minus the inner shell
        region = new Region();
        region.add(outerRect);
        region.subtract(innerRect);

        overlayShell.setRegion(region);
        region.dispose();

        // Draw rectangle with new GC
        GC gc = new GC(overlayShell);
        gc.setLineWidth(lineWidth);
        gc.setForeground(color);
        gc.drawRectangle(innerRect);
        gc.dispose();
    }

    private void initListeners() {
       controlListener = new ControlListener() {

          @Override
          public void controlResized(ControlEvent e) {
            redraw();
          }

          @Override
          public void controlMoved(ControlEvent e) {
            redraw();
          }
        };

        shellListener = new ShellListener() {

          @Override
          public void shellIconified(ShellEvent e) {
            overlayShell.setVisible(false);        
          }

          @Override
          public void shellDeiconified(ShellEvent e) {
            overlayShell.setVisible(true);                
          }

          @Override
          public void shellDeactivated(ShellEvent e) {
            overlayShell.setVisible(false);         
          }

          @Override
          public void shellClosed(ShellEvent e) {
            dispose();        
          }

          @Override
          public void shellActivated(ShellEvent e) {
            overlayShell.setVisible(true);          
          }
        };

        paintListener = new PaintListener() {

          @Override
          public void paintControl(PaintEvent e) {
            redraw();
          }
        };
    }
}
0 голосов
/ 04 мая 2018

Платформа Eclipse делает это, создавая и закрашивая оверлейную оболочку, аккуратно расположенную поверх базовой оболочки. Наложение создается с помощью SWT.NO_TRIM | SWT.ON_TOP, и его позиция отслеживает базовую базовую оболочку. См. Пример e4 Overlay .

...