Skip to content

Commit

Permalink
Merge pull request #129 from creme332/anim
Browse files Browse the repository at this point in the history
implement sidebar animation
  • Loading branch information
creme332 authored Jun 27, 2024
2 parents 9eb75c4 + 4b830f7 commit 88abed6
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,139 @@
package com.github.creme332.controller;

import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

import com.github.creme332.model.AppState;
import com.github.creme332.model.CanvasModel;
import com.github.creme332.model.Mode;
import com.github.creme332.view.CanvasConsole;
import com.github.creme332.view.SideMenuPanel;
import com.github.creme332.view.Toast;

public class CanvasConsoleController implements PropertyChangeListener {
private Timer timer;
private Toast toast;
private CanvasConsole console;
private CanvasModel model;

public CanvasConsoleController(AppState app, CanvasConsole console) {
this.console = console;
this.model = app.getCanvasModel();
toast = console.getToast();
app.addPropertyChangeListener(this);

new ToolBarController(console.getToolbar(), app.getCanvasModel());
new SideMenuController(app, console.getSidebar());
new ZoomPanelController(app, console.getZoomPanel());

if (!app.getSideBarVisibility()) {
System.out.println(console.getPreferredSize());
console.setPreferredSize(console.getPreferredSize());
}
}

@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("activateToast".equals(evt.getPropertyName())) {
Mode currentMode = (Mode) evt.getNewValue();
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if ("activateToast".equals(propertyName)) {
Mode currentMode = (Mode) e.getNewValue();

toast.setTitleText(currentMode.getTitle());
toast.setInstructionText(currentMode.getInstructions());
showTemporaryToast();
}

if ("sidebarVisibility".equals(propertyName)) {
boolean openSidebar = (boolean) e.getNewValue();
if (openSidebar) {
animateSidebarOpen();
} else {
animateSidebarClose();
}
}
}

/**
* Animates sidebar opening. It decreases the width of the canvas console so
* that the sidebar which was initially out of frame becomes visible.
*/
private void animateSidebarOpen() {
/**
* Speed at which sidebar opens in pixels per nanosecond.
*/
final int openingSpeed = 5;
/**
* Initial width of canvas console such that sidebar is hidden.
*/
final int initialWidth = console.getRootPane().getWidth() + SideMenuPanel.PREFERRED_WIDTH;

/**
* Final width of canvas console such that sidebar is visible.
*/
final int finalWidth = model.getCanvasDimension().width;

Thread th = new Thread() {
@Override
public void run() {
for (int i = initialWidth; i >= finalWidth; i -= openingSpeed) {
try {
TimeUnit.NANOSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
int newWidth = Math.max(finalWidth, i);
console.setSize(new Dimension(newWidth, console.getHeight()));
console.revalidate();
console.repaint();
}

}
};
th.start();
}

/**
* Animates sidebar closing. It increases the width of the canvas console so
* that the sidebar becomes hidden (since sidebar moves out of frame).
*/
private void animateSidebarClose() {
/**
* Speed at which sidebar closes in pixels per nanosecond.
*/
final int closingSpeed = 6;

/**
* Initial width of canvas console such that sidebar is visible.
*/
final int initialWidth = console.getRootPane().getWidth();

/**
* Final width of canvas console such that sidebar is hidden.
*/
final int finalWidth = initialWidth + SideMenuPanel.PREFERRED_WIDTH;

Thread th = new Thread() {
@Override
public void run() {
for (int i = initialWidth; i <= finalWidth; i += closingSpeed) {
try {
TimeUnit.NANOSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
int newWidth = Math.min(finalWidth, i);
console.setSize(new Dimension(newWidth, console.getHeight()));
console.revalidate();
console.repaint();
}
}

};
th.start();
}

private void showTemporaryToast() {
Expand Down
38 changes: 24 additions & 14 deletions src/main/java/com/github/creme332/controller/FrameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ public void keyPressed(KeyEvent e) {
}

/**
* Resizes frame and its components when frame dimensions changes
* Resizes frame and its components when frame dimensions changes. This is the
* function responsible for setting the size of canvas and canvas control.
*/
private void resizeEverything() {
int frameWidth = frame.getWidth();
int frameHeight = frame.getHeight();
final int frameWidth = frame.getWidth();
final int frameHeight = frame.getHeight();

Dimension mainDimension = new Dimension(frameWidth, frameHeight - MenuBar.HEIGHT - 60);
Dimension canvasDimension = new Dimension(frameWidth, frameHeight - MenuBar.HEIGHT - 60);

if (DesktopApi.getOs() == EnumOS.LINUX) {
/**
Expand All @@ -91,31 +92,40 @@ private void resizeEverything() {
* overflowing
*/

mainDimension = new Dimension(frameWidth - 80, frameHeight - MenuBar.HEIGHT - 100);
canvasDimension = new Dimension(frameWidth - 80, frameHeight - MenuBar.HEIGHT - 100);
}

Rectangle mainBounds = new Rectangle(mainDimension);

JLayeredPane canvasScreen = frame.getCanvasScreen();
CanvasConsole canvasControl = (CanvasConsole) canvasScreen.getComponent(0);
Canvas canvas = (Canvas) canvasScreen.getComponent(1);

// update canvasScreen dimensions
canvasScreen.setMaximumSize(mainDimension);
canvasScreen.setMaximumSize(canvasDimension);

// update canvas position
canvas.setMaximumSize(canvasDimension);
canvas.setBounds(new Rectangle(canvasDimension));

/**
* Calculate dimensions of canvas control, taking into account whether the
* sidebar is visible. Note: Hiding of the sidebar is made possible by pushing
* it out the frame. This makes sidebar animation easier.
*/

final boolean sidebarEnabled = app.getSideBarVisibility();
final Dimension canvasControlDimension = new Dimension(
canvasDimension.width + (sidebarEnabled ? 0 : SideMenuPanel.PREFERRED_WIDTH),
canvasDimension.height);

// update canvas control dimensions]
canvasControl.setMaximumSize(mainDimension);
canvasControl.setBounds(mainBounds);
canvasControl.setMaximumSize(canvasControlDimension);
canvasControl.setBounds(new Rectangle(canvasControlDimension));
canvasControl.revalidate();

// update sidebar height
frame.getCanvasConsole().getSidebar().setMaximumSize(new Dimension(SideMenuPanel.PREFERRED_WIDTH,
frameHeight - MenuBar.HEIGHT));

// update canvas position
canvas.setMaximumSize(mainDimension);
canvas.setBounds(mainBounds);

frame.repaint();
frame.revalidate();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.github.creme332.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
Expand All @@ -17,7 +16,7 @@
/**
* Controller responsible for managing sidebar in CanvasConsole.
*/
public class SideMenuController implements PropertyChangeListener {
public class SideMenuController {

private static final String PROJECT_INFO = """
Polydraw is an application for drawing rasterized shapes, inspired by Geogebra Classic.
Expand All @@ -33,10 +32,6 @@ public class SideMenuController implements PropertyChangeListener {
public SideMenuController(AppState app, SideMenuPanel sidebar) {
this.sidebar = sidebar;

app.addPropertyChangeListener(this);

sidebar.setVisible(app.getSideBarVisibility());

// set default values in canvas settings
sidebar.getGridLinesCheckBox().setSelected(app.getCanvasModel().isGuidelinesEnabled());
sidebar.getAxesCheckBox().setSelected(app.getCanvasModel().isAxesVisible());
Expand All @@ -59,14 +54,6 @@ public void mouseMoved(MouseEvent e) {
});
}

@Override
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if ("sidebarVisibility".equals(propertyName)) {
sidebar.setVisible((boolean) e.getNewValue());
}
}

private void initializeButtonListeners(AppState app) {
CanvasModel canvasModel = app.getCanvasModel();

Expand Down
6 changes: 2 additions & 4 deletions src/main/java/com/github/creme332/view/CanvasConsole.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,15 @@ public class CanvasConsole extends JPanel {

transient CanvasModel canvasModel;

public CanvasConsole(CanvasModel canvasModel, boolean isSidebarVisible, Mode defaultMode) {
public CanvasConsole(CanvasModel canvasModel, Mode defaultMode) {
this.canvasModel = canvasModel;
toast = new Toast(defaultMode);

setOpaque(false); // make panel transparent
setOpaque(false);
setLayout(new BorderLayout());

this.add(createMainPanel(), BorderLayout.CENTER);

sideMenu.setVisible(isSidebarVisible);

this.add(sideMenu, BorderLayout.EAST);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/github/creme332/view/Frame.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public Frame(AppState app)
initFrameProperties();

menubar = new MenuBar(app.getMenuModels());
canvasConsole = new CanvasConsole(app.getCanvasModel(), app.getSideBarVisibility(), app.getMode());
canvasConsole = new CanvasConsole(app.getCanvasModel(), app.getMode());
canvas = new Canvas(app.getCanvasModel());
tutorialCenter = new TutorialCenter();

Expand Down

0 comments on commit 88abed6

Please sign in to comment.