Skip to content

Commit

Permalink
Improved open_hexagon action to include a region guide box
Browse files Browse the repository at this point in the history
  • Loading branch information
Martomate committed Jan 18, 2020
1 parent e71b142 commit 834a93f
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 72 deletions.
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=0.13.17
sbt.version=1.2.8
Binary file added src/main/resources/icons/open_hexagon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ class TriPaintController(val model: TriPaintModel) extends TriPaintViewListener

model.imageGrid.setImageSizeIfEmpty(view.askForImageSize().getOrElse(32))

override def action_new(): Unit = NewAction.perform(model, view)
override def action_open(): Unit = OpenAction.perform(model, view)
override def action_openHexagon(): Unit = OpenHexagonAction.perform(model, view)
override def action_save(): Unit = SaveAction.perform(model, view)
override def action_saveAs(): Unit = SaveAsAction.perform(model, view)
override def action_exit(): Unit = ExitAction.perform(model, view)
private def perform(action: Action): Unit = action.perform(model, view)

override def action_undo(): Unit = UndoAction.perform(model, view)
override def action_redo(): Unit = RedoAction.perform(model, view)
override def action_new(): Unit = perform(NewAction)
override def action_open(): Unit = perform(OpenAction)
override def action_openHexagon(): Unit = perform(OpenHexagonAction)
override def action_save(): Unit = perform(SaveAction)
override def action_saveAs(): Unit = perform(SaveAsAction)
override def action_exit(): Unit = perform(ExitAction)

override def action_blur(): Unit = BlurAction.perform(model, view)
override def action_motionBlur(): Unit = MotionBlurAction.perform(model, view)
override def action_randomNoise(): Unit = RandomNoiseAction.perform(model, view)
override def action_scramble(): Unit = ScrambleAction.perform(model, view)
override def action_undo(): Unit = perform(UndoAction)
override def action_redo(): Unit = perform(RedoAction)

override def action_blur(): Unit = perform(BlurAction)
override def action_motionBlur(): Unit = perform(MotionBlurAction)
override def action_randomNoise(): Unit = perform(RandomNoiseAction)
override def action_scramble(): Unit = perform(ScrambleAction)

override def requestExit(): Boolean = ExitAction.do_exit(model, view)
override def requestImageRemoval(image: ImageContent): Unit = new RemoveImageAction(image).perform(model, view)
override def requestImageRemoval(image: ImageContent): Unit = perform(new RemoveImageAction(image))
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,18 @@ import scala.util.{Failure, Success}

object OpenAction extends Action {
override def perform(model: TriPaintModel, view: TriPaintView): Unit = {
view.askForFileToOpen() foreach { file =>
val imageSize = model.imageGrid.imageSize
val offset = view.askForOffset().getOrElse(0, 0)

model.imagePool.fromFile(SaveLocation(file, offset), imageSize) match {
case Success(storage) =>
view.askForWhereToPutImage() foreach { coords =>
val image = makeImageContent(model, TriImageCoords(coords._1, coords._2), storage)
addImage(model, image)
}
case Failure(exc) =>
exc.printStackTrace()
}
val imageSize = model.imageGrid.imageSize
for {
file <- view.askForFileToOpen()
offset <- view.askForOffset(file, imageSize, imageSize)
coords <- view.askForWhereToPutImage()
} model.imagePool.fromFile(SaveLocation(file, offset), imageSize) match {
case Success(storage) =>
val imageCoords = TriImageCoords(coords._1, coords._2)
val image = makeImageContent(model, imageCoords, storage)
addImage(model, image)
case Failure(exc) =>
exc.printStackTrace()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@ import scala.util.{Failure, Success}

object OpenHexagonAction extends Action {
override def perform(model: TriPaintModel, view: TriPaintView): Unit = {
view.askForFileToOpen() foreach { file =>
val imageSize = model.imageGrid.imageSize
val offset = view.askForOffset().getOrElse(0, 0)

view.askForWhereToPutImage() foreach { coords =>
for (idx <- 0 until 6) {
model.imagePool.fromFile(SaveLocation(file, (offset._1 + idx * imageSize, offset._2)), imageSize) match {
case Success(storage) =>
val off = coordOffset(idx)
val imageCoords = TriImageCoords(coords._1 + off._1, coords._2 + off._2)
val image = makeImageContent(model, imageCoords, storage)
addImage(model, image)
case Failure(exc) =>
exc.printStackTrace()
}
}
val imageSize = model.imageGrid.imageSize
for {
file <- view.askForFileToOpen()
offset <- view.askForOffset(file, imageSize * 6, imageSize)
coords <- view.askForWhereToPutImage()
} for (idx <- 0 until 6) {
model.imagePool.fromFile(SaveLocation(file, (offset._1 + idx * imageSize, offset._2)), imageSize) match {
case Success(storage) =>
val off = coordOffset(idx)
val imageCoords = TriImageCoords(coords._1 + off._1, coords._2 + off._2)
val image = makeImageContent(model, imageCoords, storage)
addImage(model, image)
case Failure(exc) =>
exc.printStackTrace()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ trait TriPaintView extends ImageSaveCollisionHandler {
def askForWhereToPutImage(): Option[(Int, Int)]
def askForSaveFile(image: ImageContent): Option[File]
def askForFileToOpen(): Option[File]
def askForOffset(): Option[(Int, Int)]
def askForOffset(file: File, width: Int, height: Int): Option[(Int, Int)]

def askForBlurRadius(): Option[Int]
def askForMotionBlurRadius(): Option[Int]
Expand Down
84 changes: 77 additions & 7 deletions src/main/scala/com/martomate/tripaint/view/gui/DialogUtils.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.martomate.tripaint.view.gui

import java.io.{File, FileInputStream}

import com.martomate.tripaint.model.content.ImageContent
import com.martomate.tripaint.model.pool.ImagePool
import com.martomate.tripaint.view.image.TriImage
import scalafx.application.Platform
import scalafx.beans.property.StringProperty
import scalafx.geometry.{Orientation, Rectangle2D}
import scalafx.scene.Node
import scalafx.scene.control._
import scalafx.scene.layout.{GridPane, Region, VBox}
import scalafx.scene.image.{Image, ImageView}
import scalafx.scene.layout._
import scalafx.scene.paint.Color

import scala.util.Try

Expand All @@ -23,12 +28,12 @@ object DialogUtils {
val uintRestriction: String => Boolean = customIntRestriction(_ >= 0)

def doubleTF: TextField = makeTF(doubleRestriction)
def intTF: TextField = makeTF(doubleRestriction)
def uintTF: TextField = makeTF(doubleRestriction)
def intTF: TextField = makeTF(intRestriction)
def uintTF: TextField = makeTF(uintRestriction)

def makeTF(restriction: String => Boolean): TextField = {
val tf = new TextField
DialogUtils.restrictTextField(tf, restriction)
restrictTextField(tf, restriction)
tf
}

Expand Down Expand Up @@ -61,7 +66,9 @@ object DialogUtils {
dialog.headerText = headerText
dialog.contentText = contentText
dialog.graphic = graphic
dialog.dialogPane().setContent(new VBox(content: _*))
val contentBox = new VBox(content: _*)
contentBox.setSpacing(10)
dialog.dialogPane().setContent(contentBox)
dialog.resultConverter = resultConverter
for (b <- buttons) dialog.dialogPane().getButtonTypes add b
if (nodeWithFocus != null) dialog.setOnShowing(_ => Platform.runLater(nodeWithFocus.requestFocus()))
Expand Down Expand Up @@ -93,14 +100,77 @@ object DialogUtils {
)
}

def askForXY(title: String, headerText: String, imagePreview: (File, Int, Int)): Option[(Int, Int)] = {
val (previewFile, previewWidth, previewHeight) = imagePreview

val xCoordTF = DialogUtils.uintTF
val yCoordTF = DialogUtils.uintTF

val coordsFromTF = () => {
val xt = xCoordTF.text()
val yt = yCoordTF.text()
Try ((if (xt != "") xt.toInt else 0,
if (yt != "") yt.toInt else 0))
}

val previewPane = new Pane
previewPane.setMinSize(previewWidth, previewHeight)
previewPane.setMaxSize(previewWidth, previewHeight)

{
import javafx.scene.layout._
import javafx.scene.paint.Color
val stroke = new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)
previewPane.delegate.setBorder(new Border(stroke))
}

val wholeImage = new ImageView(new Image(new FileInputStream(previewFile)))

val previewStack = new Pane
previewStack.delegate.getChildren.addAll(wholeImage, previewPane)

def updatePreviewAction: Unit = {
coordsFromTF() foreach {
case (x, y) =>
previewPane.setLayoutX(x)
previewPane.setLayoutY(y)
}
}

updatePreviewAction

xCoordTF.text.onChange(updatePreviewAction)
yCoordTF.text.onChange(updatePreviewAction)

getValueFromCustomDialog[(Int, Int)](
title = title,
headerText = headerText,

content = Seq(makeGridPane(Seq(
Seq(new Label("X coordinate:"), xCoordTF),
Seq(new Label("Y coordinate:"), yCoordTF)
)), Separator(Orientation.Horizontal), previewStack),

resultConverter = {
case ButtonType.OK => coordsFromTF().getOrElse(null)
case _ => null
},

nodeWithFocus = xCoordTF,

buttons = Seq(ButtonType.OK, ButtonType.Cancel)
)
}

def askForWhereToPutImage(): Option[(Int, Int)] = askForXY(
title = "New image",
headerText = "Please enter where it should be placed."
)

def askForOffset(): Option[(Int, Int)] = askForXY(
def askForOffset(file: File, width: Int, height: Int): Option[(Int, Int)] = askForXY(
title = "Open partial image",
headerText = "Which part of the image should be opened? Please enter the top left corner:"
headerText = "Which part of the image should be opened? Please enter the top left corner:",
imagePreview = (file, width, height)
)

def getValueFromDialog[T](imagePool: ImagePool,
Expand Down
47 changes: 26 additions & 21 deletions src/main/scala/com/martomate/tripaint/view/gui/MainStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@ import scalafx.stage.FileChooser.ExtensionFilter
import scala.util.Try

class MainStageButtons(control: TriPaintViewListener) {
val New: MenuBarAction = MenuBarAction.apply("New", "new", new KeyCodeCombination(KeyCode.N, KeyCombination.ControlDown)) (control.action_new())
val Open: MenuBarAction = MenuBarAction.apply("Open", "open", new KeyCodeCombination(KeyCode.O, KeyCombination.ControlDown)) (control.action_open())
val OpenHexagon: MenuBarAction = MenuBarAction.apply("Open hexagon") (control.action_openHexagon())
val Save: MenuBarAction = MenuBarAction.apply("Save", "save", new KeyCodeCombination(KeyCode.S, KeyCombination.ControlDown)) (control.action_save())
val SaveAs: MenuBarAction = MenuBarAction.apply("Save As", accelerator = new KeyCodeCombination(KeyCode.S, KeyCombination.ControlDown, KeyCombination.ShiftDown)) (control.action_saveAs())
val Exit: MenuBarAction = MenuBarAction.apply("Exit") (control.action_exit())
val Undo: MenuBarAction = MenuBarAction.apply("Undo", "undo", new KeyCodeCombination(KeyCode.Z, KeyCombination.ControlDown)) (control.action_undo())
val Redo: MenuBarAction = MenuBarAction.apply("Redo", "redo", new KeyCodeCombination(KeyCode.Y, KeyCombination.ControlDown)) (control.action_redo())
val Cut: MenuBarAction = MenuBarAction.apply("Cut", "cut") ()
val Copy: MenuBarAction = MenuBarAction.apply("Copy", "copy") ()
val Paste: MenuBarAction = MenuBarAction.apply("Paste", "paste") ()
val Move: MenuBarAction = MenuBarAction.apply("Move", "move") ()
val Scale: MenuBarAction = MenuBarAction.apply("Scale", "scale") ()
val Rotate: MenuBarAction = MenuBarAction.apply("Rotate", "rotate") ()
val Blur: MenuBarAction = MenuBarAction.apply("Blur") (control.action_blur())
val MotionBlur: MenuBarAction = MenuBarAction.apply("Motion blur") (control.action_motionBlur())
val RandomNoise: MenuBarAction = MenuBarAction.apply("Random noise") (control.action_randomNoise())
val Scramble: MenuBarAction = MenuBarAction.apply("Scramble") (control.action_scramble())
val New: MenuBarAction = MenuBarAction("New", "new", new KeyCodeCombination(KeyCode.N, KeyCombination.ControlDown)) (control.action_new())
val Open: MenuBarAction = MenuBarAction("Open", "open", new KeyCodeCombination(KeyCode.O, KeyCombination.ControlDown)) (control.action_open())
val OpenHexagon: MenuBarAction = MenuBarAction("Open hexagon", "open_hexagon", new KeyCodeCombination(KeyCode.H, KeyCombination.ControlDown)) (control.action_openHexagon())
val Save: MenuBarAction = MenuBarAction("Save", "save", new KeyCodeCombination(KeyCode.S, KeyCombination.ControlDown)) (control.action_save())
val SaveAs: MenuBarAction = MenuBarAction("Save As", accelerator = new KeyCodeCombination(KeyCode.S, KeyCombination.ControlDown, KeyCombination.ShiftDown)) (control.action_saveAs())
val Exit: MenuBarAction = MenuBarAction("Exit") (control.action_exit())
val Undo: MenuBarAction = MenuBarAction("Undo", "undo", new KeyCodeCombination(KeyCode.Z, KeyCombination.ControlDown)) (control.action_undo())
val Redo: MenuBarAction = MenuBarAction("Redo", "redo", new KeyCodeCombination(KeyCode.Y, KeyCombination.ControlDown)) (control.action_redo())
val Cut: MenuBarAction = MenuBarAction("Cut", "cut") ()
val Copy: MenuBarAction = MenuBarAction("Copy", "copy") ()
val Paste: MenuBarAction = MenuBarAction("Paste", "paste") ()
val Move: MenuBarAction = MenuBarAction("Move", "move") ()
val Scale: MenuBarAction = MenuBarAction("Scale", "scale") ()
val Rotate: MenuBarAction = MenuBarAction("Rotate", "rotate") ()
val Blur: MenuBarAction = MenuBarAction("Blur") (control.action_blur())
val MotionBlur: MenuBarAction = MenuBarAction("Motion blur") (control.action_motionBlur())
val RandomNoise: MenuBarAction = MenuBarAction("Random noise") (control.action_randomNoise())
val Scramble: MenuBarAction = MenuBarAction("Scramble") (control.action_scramble())
}

class MainStage(controls: TriPaintViewListener, model: TriPaintModel) extends PrimaryStage with TriPaintView {
Expand All @@ -52,6 +52,8 @@ class MainStage(controls: TriPaintViewListener, model: TriPaintModel) extends Pr
private val imageTabs: ImageTabs = new ImageTabs(controls, model)
private val colorBox: VBox = makeColorBox()

private var currentFolder: Option[File] = None

title = "TriPaint"
onCloseRequest = e => {
if (!controls.requestExit()) e.consume()
Expand Down Expand Up @@ -109,8 +111,11 @@ class MainStage(controls: TriPaintViewListener, model: TriPaintModel) extends Pr

override def askForFileToOpen(): Option[File] = {
val chooser = new FileChooser
currentFolder.foreach(chooser.initialDirectory = _)
chooser.title = "Open file"
Option(chooser.showOpenDialog(this))
val result = Option(chooser.showOpenDialog(this))
result.foreach(r => currentFolder = Some(r.getParentFile))
result
}

override def askForWhereToPutImage(): Option[(Int, Int)] = {
Expand Down Expand Up @@ -187,8 +192,8 @@ class MainStage(controls: TriPaintViewListener, model: TriPaintModel) extends Pr
alert
}

override def askForOffset(): Option[(Int, Int)] = {
DialogUtils.askForOffset()
override def askForOffset(file: File, width: Int, height: Int): Option[(Int, Int)] = {
DialogUtils.askForOffset(file, width, height)
}

override def shouldReplaceImage(currentImage: ImageStorage, newImage: ImageStorage, location: SaveLocation): Option[Boolean] = {
Expand Down

0 comments on commit 834a93f

Please sign in to comment.