diff --git a/SmartNotes/src/com/madeorsk/smartnotes/ExplorerItem.java b/SmartNotes/src/com/madeorsk/smartnotes/ExplorerItem.java index 71a6ea6..1a8d580 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/ExplorerItem.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/ExplorerItem.java @@ -1,7 +1,6 @@ package com.madeorsk.smartnotes; import com.madeorsk.smartnotes.notes.Note; -import com.madeorsk.smartnotes.notes.TextNote; import com.madeorsk.smartnotes.paths.FolderPath; import javafx.event.EventHandler; @@ -34,7 +33,7 @@ public class ExplorerItem extends HBox else { explorer.requestLoad((Note) ExplorerItem.this.item); - SmartNotes.instance.setContent(((TextNote) ExplorerItem.this.item).getNoteBox(explorer)); + SmartNotes.instance.setContent(((Note) ExplorerItem.this.item).getNoteBox(explorer)); } } }); @@ -53,7 +52,7 @@ public class ExplorerItem extends HBox else { Note note = (Note) this.item; - this.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/TextNoteIcon-" + note.getNoteColor().name() + ".png"))); + this.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/" + note.getClass().getSimpleName() + "Icon-" + note.getNoteColor().name() + ".png"))); Label noteNameLabel = new Label(note.getName()); noteNameLabel.setId("noteItemName"); this.getChildren().add(noteNameLabel); diff --git a/SmartNotes/src/com/madeorsk/smartnotes/ListBox.java b/SmartNotes/src/com/madeorsk/smartnotes/ListBox.java new file mode 100644 index 0000000..47c180e --- /dev/null +++ b/SmartNotes/src/com/madeorsk/smartnotes/ListBox.java @@ -0,0 +1,229 @@ +package com.madeorsk.smartnotes; + +import java.util.HashMap; +import java.util.Map; + +import javafx.animation.FadeTransition; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableBooleanValue; +import javafx.beans.value.ObservableValue; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Cursor; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.util.Duration; + +public class ListBox extends ScrollPane +{ + private VBox main; + private VBox listContainer; + + private Runnable listChangeListener; + + public ListBox() + { + this.setFitToHeight(true); + this.setFitToWidth(true); + + this.main = new VBox(); + this.main.setPadding(new Insets(0, 15, 0, 15)); + this.listContainer = new VBox(); + this.main.getChildren().add(this.listContainer); + + final HBox addListItemBox = new HBox(); + { + addListItemBox.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/AddCheckbox.png"))); + Label addListItemLabel = new Label("Add a new item"); + addListItemLabel.setPadding(new Insets(0, 0, 0, 13)); + addListItemLabel.setId("text"); + addListItemBox.getChildren().add(addListItemLabel); + addListItemBox.setAlignment(Pos.CENTER_LEFT); + addListItemBox.setCursor(Cursor.HAND); + // Fade and opacity + addListItemBox.setOpacity(0.4); + addListItemBox.setOnMouseEntered(new EventHandler() + { + @Override + public void handle(MouseEvent e) + { + FadeTransition transition = new FadeTransition(Duration.millis(200), addListItemBox); + transition.setFromValue(0.4); + transition.setToValue(1.0); + transition.play(); + } + }); + addListItemBox.setOnMouseExited(new EventHandler() + { + @Override + public void handle(MouseEvent e) + { + FadeTransition transition = new FadeTransition(Duration.millis(200), addListItemBox); + transition.setFromValue(1.0); + transition.setToValue(0.4); + transition.play(); + } + }); + addListItemBox.setOnMouseClicked(new EventHandler() + { + @Override + public void handle(MouseEvent e) + { + ListBox.this.listContainer.getChildren().add(new ListBoxItem("")); + } + }); + } + this.main.getChildren().add(addListItemBox); + + this.setContent(this.main); + } + + public void updateList(Map content) + { + this.listContainer.getChildren().clear(); + for(String item : content.keySet()) + this.listContainer.getChildren().add(new ListBoxItem(item).setChecked(content.get(item).booleanValue())); + } + + public void setListChangeListener(Runnable listener) + { + this.listChangeListener = listener; + } + + public Map getList() + { + Map list = new HashMap(); + for(Node child : this.listContainer.getChildren()) + { + ListBoxItem item = (ListBoxItem) child; + if (item.getText() != null && !item.getText().isEmpty()) + list.put(item.getText(), item.isChecked()); + } + return list; + } + + private class ListBoxItem extends HBox + { + private ListCheckbox checkbox; + private TextField field; + + public ListBoxItem(String text) + { + ChangeListener change = new ChangeListener() + { + @Override + public void changed(ObservableValue ov, Object oldValue, Object newValue) + { + if (ListBox.this.listChangeListener != null) + ListBox.this.listChangeListener.run(); + } + }; + this.checkbox = new ListCheckbox(); + this.checkbox.checkedProperty().addListener(change); + this.getChildren().add(this.checkbox); + this.field = new TextField(text); + this.field.setId("text"); + this.field.prefWidthProperty().bind(ListBox.this.listContainer.widthProperty().subtract(this.checkbox.widthProperty())); + this.field.textProperty().addListener(change); + this.getChildren().add(this.field); + } + + public String getText() + { + return this.field.getText(); + } + + public ListBoxItem setChecked(boolean checked) + { + this.checkbox.setChecked(checked); + return this; + } + public boolean isChecked() + { + return this.checkbox.isChecked(); + } + + private class ListCheckbox extends VBox + { + private BooleanProperty checked = new SimpleBooleanProperty(); + + public ListCheckbox() + { + this.setId("imageButton"); + this.setAlignment(Pos.CENTER); + this.setCursor(Cursor.HAND); + this.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/Checkbox-unchecked.png"))); + + /*this.setOpacity(0.4); + this.setOnMouseEntered(new EventHandler() + { + @Override + public void handle(MouseEvent e) + { + if (!ListCheckbox.this.isChecked()) + { + FadeTransition transition = new FadeTransition(Duration.millis(200), ListCheckbox.this); + transition.setFromValue(0.4); + transition.setToValue(1.0); + transition.play(); + } + } + }); + this.setOnMouseExited(new EventHandler() + { + @Override + public void handle(MouseEvent e) + { + if (!ListCheckbox.this.isChecked()) + { + FadeTransition transition = new FadeTransition(Duration.millis(200), ListCheckbox.this); + transition.setFromValue(1.0); + transition.setToValue(0.4); + transition.play(); + } + } + });*/ + + this.setOnMouseClicked(new EventHandler() + { + @Override + public void handle(MouseEvent e) + { + if (ListCheckbox.this.isChecked()) + ListCheckbox.this.setChecked(false); + else + ListCheckbox.this.setChecked(true); + } + }); + } + + public void setChecked(boolean checked) + { + this.checked.set(checked); + ListCheckbox.this.getChildren().clear(); + if (checked) + ListCheckbox.this.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/Checkbox-checked.png"))); + else + ListCheckbox.this.getChildren().add(new ImageView(new Image("/com/madeorsk/smartnotes/res/Checkbox-unchecked.png"))); + } + public ObservableBooleanValue checkedProperty() + { + return this.checked; + } + public boolean isChecked() + { + return this.checked.get(); + } + } + } +} diff --git a/SmartNotes/src/com/madeorsk/smartnotes/NotesExplorer.java b/SmartNotes/src/com/madeorsk/smartnotes/NotesExplorer.java index ccdb695..5f80e01 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/NotesExplorer.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/NotesExplorer.java @@ -177,6 +177,18 @@ public class NotesExplorer extends VBox } } + public void replaceNote(Note oldNote, Note newNote) + { + for(int key : this.notes.keySet()) + { + if (this.notes.get(key).equals(oldNote)) + { + this.notes.get(key).delete(this.saves, key); + this.notes.put(key, newNote); + } + } + } + public void requestSave(Note note) { for (int key : this.notes.keySet()) diff --git a/SmartNotes/src/com/madeorsk/smartnotes/TypeSelector.java b/SmartNotes/src/com/madeorsk/smartnotes/TypeSelector.java index 66b92d7..990d0f6 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/TypeSelector.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/TypeSelector.java @@ -16,19 +16,53 @@ import javafx.util.Duration; public class TypeSelector extends HBox { - public TypeSelector(NotesExplorer explorer, Note note) + public TypeSelector(final NotesExplorer explorer, final Note note) { this.setSpacing(15); TypeItem textNoteItem = new TypeItem("/com/madeorsk/smartnotes/res/TextNoteChoice.png"); { if (note instanceof TextNote) textNoteItem.setSelected(true); + else + { + textNoteItem.setOnMouseClicked(new EventHandler() + { + @Override + public void handle(MouseEvent event) + { + Note textNote = new TextNote(); + textNote.setName(note.getName()); + textNote.setTextContent(note.getTextContent()); + textNote.setNoteColor(note.getNoteColor()); + explorer.replaceNote(note, textNote); + explorer.requestSave(textNote); + SmartNotes.instance.setContent(textNote.getNoteBox(explorer)); + } + }); + } } this.getChildren().add(textNoteItem); TypeItem listNoteItem = new TypeItem("/com/madeorsk/smartnotes/res/ListNoteChoice.png"); { if (note instanceof ListNote) listNoteItem.setSelected(true); + else + { + listNoteItem.setOnMouseClicked(new EventHandler() + { + @Override + public void handle(MouseEvent event) + { + Note listNote = new ListNote(); + listNote.setName(note.getName()); + listNote.setTextContent(note.getTextContent()); + listNote.setNoteColor(note.getNoteColor()); + explorer.replaceNote(note, listNote); + explorer.requestSave(listNote); + SmartNotes.instance.setContent(listNote.getNoteBox(explorer)); + } + }); + } } this.getChildren().add(listNoteItem); TypeItem imageNoteItem = new TypeItem("/com/madeorsk/smartnotes/res/ImageNoteChoice.png"); diff --git a/SmartNotes/src/com/madeorsk/smartnotes/notes/ListNote.java b/SmartNotes/src/com/madeorsk/smartnotes/notes/ListNote.java index 5da30e8..161e76c 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/notes/ListNote.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/notes/ListNote.java @@ -1,13 +1,18 @@ package com.madeorsk.smartnotes.notes; +import java.io.File; import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; +import com.madeorsk.smartnotes.ListBox; import com.madeorsk.smartnotes.NoteColorSelector; import com.madeorsk.smartnotes.NotesExplorer; import com.madeorsk.smartnotes.SavesManager; import com.madeorsk.smartnotes.SmartNotes; import com.madeorsk.smartnotes.TypeSelector; +import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; @@ -24,9 +29,13 @@ import javafx.scene.layout.VBox; public class ListNote extends Note { + private ListBox listBox; + private boolean loading = false; + public ListNote() { this.setName("Text_" + Calendar.getInstance().get(Calendar.YEAR) + "." + Calendar.getInstance().get(Calendar.MONTH) + "." + Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + "-" + Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE)); + this.listBox = new ListBox(); } @Override @@ -98,11 +107,17 @@ public class ListNote extends Note } box.getChildren().add(nameField); - TextArea textArea = new TextArea(); + // + + HBox separator = new HBox(); + separator.setId("separator"); + separator.setPrefHeight(5); + + final TextArea textArea = new TextArea(); { - textArea.setId("textArea"); + textArea.setId("text"); textArea.setWrapText(true); - textArea.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty())); + textArea.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty()).subtract(separator.heightProperty()).divide(2)); textArea.setText(this.getTextContent()); textArea.textProperty().addListener(new ChangeListener() { @@ -113,35 +128,91 @@ public class ListNote extends Note explorer.requestSave(ListNote.this); } }); + Platform.runLater(new Runnable() + { + @Override + public void run() + { + textArea.requestFocus(); + textArea.positionCaret(textArea.getLength()); + } + }); } box.getChildren().add(textArea); + box.getChildren().add(separator); + + this.listBox.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty()).subtract(separator.heightProperty()).divide(2)); + this.listBox.setListChangeListener(new Runnable() + { + @Override + public void run() + { + if (!ListNote.this.loading) + explorer.requestSave(ListNote.this); + } + }); + box.getChildren().add(this.listBox); + return box; } @Override public void save(SavesManager saves, int id) { - saves.writeFile(saves.getSaveFile(id), this.getName() + "\n" + this.getNoteColor().name() + "\n" + this.getTextContent()); + String fileContent = this.getName() + "\n" + this.getNoteColor().name() + "\n"; + Map list = this.listBox.getList(); + fileContent += Integer.toUnsignedString(list.keySet().size(), 16) + "\n"; + for(String key : list.keySet()) + fileContent += key + ":" + list.get(key).toString() + "\n"; + saves.writeFile(saves.getSaveFile(id), fileContent + this.getTextContent()); } @Override public boolean load(SavesManager saves, int id) { if (saves.getSaveFile(id).exists()) { + this.loading = true; + String saved = saves.readFile(saves.getSaveFile(id)); + int separatorIndex = saved.indexOf('\n'); this.setName(saved.substring(0, separatorIndex)); saved = saved.substring(separatorIndex + 1); + separatorIndex = saved.indexOf('\n'); this.setNoteColor(NoteColor.valueOf(saved.substring(0, separatorIndex))); + saved = saved.substring(separatorIndex + 1); + + separatorIndex = saved.indexOf('\n'); + int listSize = Integer.parseUnsignedInt(saved.substring(0, separatorIndex), 16); + Map list = new HashMap(); + for(int i = 0; i < listSize; i++) + { + saved = saved.substring(separatorIndex + 1); + separatorIndex = saved.indexOf('\n'); + String listItemString = saved.substring(0, separatorIndex); + int listItemSeparator = listItemString.lastIndexOf(':'); + list.put(listItemString.substring(0, listItemSeparator), Boolean.parseBoolean(listItemString.substring(listItemSeparator + 1))); + } + this.listBox.updateList(list); + if (separatorIndex < saved.length() - 1) this.setTextContent(saved.substring(separatorIndex + 1)); else this.setTextContent(""); + + this.loading = false; return true; } else return false; } + @Override + public void delete(SavesManager saves, int id) + { + File saveFile = saves.getSaveFile(id); + if (saveFile.exists()) + saveFile.delete(); + } } diff --git a/SmartNotes/src/com/madeorsk/smartnotes/notes/Note.java b/SmartNotes/src/com/madeorsk/smartnotes/notes/Note.java index 70e1598..9b6a223 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/notes/Note.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/notes/Note.java @@ -73,19 +73,22 @@ public abstract class Note implements SavableNote { this.paths.clear(); String text = this.getTextContent(); - if (text.contains("\n")) + if (text != null) { - String[] lines = text.split("\n"); - String lastLine = lines[lines.length - 1]; - for(String word : lastLine.split(" ")) - if (word.startsWith("#") && !word.equals("#")) - this.paths.add(word); - } - else - { - for(String word : text.split(" ")) - if (word.startsWith("#") && !word.equals("#")) - this.paths.add(word); + if (text.contains("\n")) + { + String[] lines = text.split("\n"); + String lastLine = lines[lines.length - 1]; + for(String word : lastLine.split(" ")) + if (word.startsWith("#") && !word.equals("#")) + this.paths.add(word); + } + else + { + for(String word : text.split(" ")) + if (word.startsWith("#") && !word.equals("#")) + this.paths.add(word); + } } } diff --git a/SmartNotes/src/com/madeorsk/smartnotes/notes/SavableNote.java b/SmartNotes/src/com/madeorsk/smartnotes/notes/SavableNote.java index cfec795..89c7097 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/notes/SavableNote.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/notes/SavableNote.java @@ -6,4 +6,5 @@ public interface SavableNote { public void save(SavesManager saves, int id); public boolean load(SavesManager saves, int id); + public void delete(SavesManager saves, int id); } diff --git a/SmartNotes/src/com/madeorsk/smartnotes/notes/TextNote.java b/SmartNotes/src/com/madeorsk/smartnotes/notes/TextNote.java index ec85eb5..f3fdb87 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/notes/TextNote.java +++ b/SmartNotes/src/com/madeorsk/smartnotes/notes/TextNote.java @@ -1,5 +1,6 @@ package com.madeorsk.smartnotes.notes; +import java.io.File; import java.util.Calendar; import com.madeorsk.smartnotes.NoteColorSelector; @@ -8,6 +9,7 @@ import com.madeorsk.smartnotes.SavesManager; import com.madeorsk.smartnotes.SmartNotes; import com.madeorsk.smartnotes.TypeSelector; +import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; @@ -100,7 +102,7 @@ public class TextNote extends Note TextArea textArea = new TextArea(); { - textArea.setId("textArea"); + textArea.setId("text"); textArea.setWrapText(true); textArea.prefHeightProperty().bind(box.heightProperty().subtract(nameField.heightProperty()).subtract(titleBox.heightProperty())); textArea.setText(this.getTextContent()); @@ -113,6 +115,15 @@ public class TextNote extends Note explorer.requestSave(TextNote.this); } }); + Platform.runLater(new Runnable() + { + @Override + public void run() + { + textArea.requestFocus(); + textArea.positionCaret(textArea.getLength()); + } + }); } box.getChildren().add(textArea); @@ -144,4 +155,11 @@ public class TextNote extends Note else return false; } + @Override + public void delete(SavesManager saves, int id) + { + File saveFile = saves.getSaveFile(id); + if (saveFile.exists()) + saveFile.delete(); + } } diff --git a/SmartNotes/src/com/madeorsk/smartnotes/res/AddCheckbox.png b/SmartNotes/src/com/madeorsk/smartnotes/res/AddCheckbox.png new file mode 100644 index 0000000..4396c56 Binary files /dev/null and b/SmartNotes/src/com/madeorsk/smartnotes/res/AddCheckbox.png differ diff --git a/SmartNotes/src/com/madeorsk/smartnotes/res/Checkbox-checked.png b/SmartNotes/src/com/madeorsk/smartnotes/res/Checkbox-checked.png new file mode 100644 index 0000000..e0eb940 Binary files /dev/null and b/SmartNotes/src/com/madeorsk/smartnotes/res/Checkbox-checked.png differ diff --git a/SmartNotes/src/com/madeorsk/smartnotes/res/Checkbox-unchecked.png b/SmartNotes/src/com/madeorsk/smartnotes/res/Checkbox-unchecked.png new file mode 100644 index 0000000..4f880ac Binary files /dev/null and b/SmartNotes/src/com/madeorsk/smartnotes/res/Checkbox-unchecked.png differ diff --git a/SmartNotes/src/com/madeorsk/smartnotes/style.css b/SmartNotes/src/com/madeorsk/smartnotes/style.css index fc1c196..061037c 100644 --- a/SmartNotes/src/com/madeorsk/smartnotes/style.css +++ b/SmartNotes/src/com/madeorsk/smartnotes/style.css @@ -17,11 +17,11 @@ -fx-border-radius: 0; } -#nameField, .scroll-pane, .scroll-pane .viewport, #textArea, #textArea .content, #imageButton +#nameField, .scroll-pane, .scroll-pane .viewport, #text, #text .content, #imageButton { -fx-background-color: transparent; } -#nameField, #textArea, #noteItemName +#nameField, #text, #noteItemName { -fx-text-fill: white; -fx-font-family: 'Cutive Mono'; @@ -31,7 +31,11 @@ { -fx-font-size: 24px; } -#textArea +#text { -fx-font-size: 20px; +} +#separator +{ + -fx-background-color: rgba(0, 0, 0, 0.15); } \ No newline at end of file