From 0e6827d25383e195cfbf4dd4b1fa3e00a4ab31c9 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sat, 26 Jul 2014 17:37:30 +0400 Subject: [PATCH 01/27] Added isSpecial() to check if contrib is to be highlighted --- app/src/processing/app/contrib/Contribution.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/contrib/Contribution.java b/app/src/processing/app/contrib/Contribution.java index 451ab7d4e..92f21d155 100644 --- a/app/src/processing/app/contrib/Contribution.java +++ b/app/src/processing/app/contrib/Contribution.java @@ -30,9 +30,10 @@ import processing.core.PApplet; abstract public class Contribution { + static final String SPECIAL_CATEGORY_NAME = "Starred"; static final List validCategories = Arrays.asList("3D", "Animation", "Data", "Geometry", "GUI", "Hardware", - "I/O", "Math", "Simulation", "Sound", "Typography", + "I/O", "Math", "Simulation", "Sound", SPECIAL_CATEGORY_NAME, "Typography", "Utilities", "Video & Vision", "Other"); //protected String category; // "Sound" @@ -165,6 +166,19 @@ abstract public class Contribution { } + /** + * Returns true if the contribution is a starred/recommended contribution, or + * is by the Processing Foundation. + * + * @return + */ + boolean isSpecial() { + if (authorList.indexOf("The Processing Foundation") != -1 || categories.contains(SPECIAL_CATEGORY_NAME)) + return true; + return false; + } + + /** * @return a single element list with "Unknown" as the category. */ From 624fc14ace3d1eeb24ea9c5619fa54e7f0da2011 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Mon, 4 Aug 2014 02:19:37 +0530 Subject: [PATCH 02/27] Implemented GUI changes related to highlighting contribs --- app/src/processing/app/contrib/ContributionPanel.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/src/processing/app/contrib/ContributionPanel.java b/app/src/processing/app/contrib/ContributionPanel.java index 68434f2bc..bc25a10ed 100644 --- a/app/src/processing/app/contrib/ContributionPanel.java +++ b/app/src/processing/app/contrib/ContributionPanel.java @@ -42,6 +42,7 @@ import javax.swing.text.html.StyleSheet; import processing.app.Base; import processing.app.Editor; +import processing.app.Toolkit; import processing.app.Language; @@ -515,6 +516,16 @@ class ContributionPanel extends JPanel { public void setContribution(Contribution contrib) { this.contrib = contrib; + + + if (contrib.isSpecial()) { + ImageIcon processingIcon = new ImageIcon(Toolkit.getLibImage("icons/pde-" + + "48" + ".png")); + JLabel iconLabel = new JLabel(processingIcon); + iconLabel.setBorder(new EmptyBorder(4, 7, 7, 7)); + iconLabel.setVerticalAlignment(SwingConstants.TOP); + add(iconLabel, BorderLayout.WEST); + } // StringBuilder nameText = new StringBuilder(); // nameText.append(""); From 30124cdd0e06f46569242a207575b0afbb123a44 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sun, 3 Aug 2014 23:51:03 +0530 Subject: [PATCH 03/27] Added validation to check if the contrib is actually starred --- .../processing/app/contrib/LocalContribution.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/src/processing/app/contrib/LocalContribution.java b/app/src/processing/app/contrib/LocalContribution.java index 1cedbd652..099514c76 100644 --- a/app/src/processing/app/contrib/LocalContribution.java +++ b/app/src/processing/app/contrib/LocalContribution.java @@ -91,6 +91,19 @@ public abstract class LocalContribution extends Contribution { name = folder.getName(); categories = defaultCategory(); } + + if (categories.contains(SPECIAL_CATEGORY_NAME)) + validateSpecial(); + } + + + private void validateSpecial() { + for (AvailableContribution available : ContributionListing.getInstance().advertisedContributions) + if (available.getName().equals(name)) { + if (!available.isSpecial()) + categories.remove(SPECIAL_CATEGORY_NAME); + } + return; } From 80be5adc5db312fc33521a921f536f38e1268278 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Tue, 12 Aug 2014 15:46:43 -0300 Subject: [PATCH 04/27] Catch MissingResourceException when language key is missing --- app/src/processing/app/Language.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/processing/app/Language.java b/app/src/processing/app/Language.java index f88dede9d..483ad765a 100644 --- a/app/src/processing/app/Language.java +++ b/app/src/processing/app/Language.java @@ -165,8 +165,13 @@ public class Language { /** Get translation from bundles. */ static public String text(String text) { - String result = init().bundle.getString(text); - return (result == null) ? text : result; + ResourceBundle bundle = init().bundle; + + try { + return bundle.getString(text); + } catch (MissingResourceException e) { + return text; + } } From 8acc44e00c66beb11a9dfaf51590c60a904cf746 Mon Sep 17 00:00:00 2001 From: liquidzym Date: Wed, 13 Aug 2014 12:54:52 +0800 Subject: [PATCH 05/27] minor fix and improved --- .../app/languages/PDE_zh.properties | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/app/src/processing/app/languages/PDE_zh.properties b/app/src/processing/app/languages/PDE_zh.properties index 7efc3fc5a..0fc905d93 100644 --- a/app/src/processing/app/languages/PDE_zh.properties +++ b/app/src/processing/app/languages/PDE_zh.properties @@ -19,11 +19,11 @@ menu.file.examples = 范例程序... menu.file.close = 关闭 menu.file.save = 保存 menu.file.save_as = 另存为... -menu.file.export_application = 导出程序... +menu.file.export_application = 输出程序... menu.file.page_setup = 页面设置 menu.file.print = 打印... menu.file.preferences = 偏好设定... -menu.file.quit = Quit +menu.file.quit = 退出 # | File | Edit | Sketch | Library | Tools | Help | # | Edit | @@ -34,7 +34,7 @@ menu.edit.cut = 剪切 menu.edit.copy = 复制 menu.edit.copy_as_html = 复制为HTML menu.edit.paste = 黏贴 -menu.edit.select_all = 选择全部 +menu.edit.select_all = 全部选择 menu.edit.auto_format = 自动对齐 menu.edit.comment_uncomment = 注释/取消注释 menu.edit.increase_indent = 增加缩进量 @@ -91,26 +91,26 @@ menu.help.visit.url = http://processing.org/ # Basics # Buttons -prompt.yes = Yes -prompt.no = No -prompt.cancel = Cancel -prompt.ok = OK -prompt.browse = Browse -prompt.export = Export +prompt.yes = 是 +prompt.no = 否 +prompt.cancel = 取消 +prompt.ok = 确认 +prompt.browse = 浏览 +prompt.export = 输出 # --------------------------------------- # Frames # Open (Frame) -open = Open a Processing sketch... +open = 打开 Processing 速写本... # Save (Frame) -save = Save sketch folder as... -save.title = Do you want to save changes to this sketch
before closing? -save.hint = If you don't save, your changes will be lost. -save.btn.save = Save -save.btn.dont_save = Don't Save +save = 保存速写本文件夹为... +save.title = 在关闭前你想要保存该速写本更改内容么
? +save.hint = 如果你没保存, 你所有的更改内容将丢失. +save.btn.save = 保存 +save.btn.dont_save = 不保存 # Preferences (Frame) preferences = 偏好设置 @@ -121,16 +121,16 @@ preferences.sketchbook_location.popup = 速写本位置 preferences.language = 语言 preferences.editor_and_console_font = 编辑器和控制台字体 preferences.editor_and_console_font.tip = \ -Select the font used in the Editor and the Console.
\ +为编辑器和控制台选择字体.
\ Only monospaced (fixed-width) fonts may be used,
\ though the list may be imperfect. preferences.editor_font_size = 编辑器字体大小 preferences.console_font_size = 控制台字体大小 preferences.background_color = 展示模式时的背景颜色 preferences.background_color.tip = \ -Select the background color used when using Present.
\ -Present is used to present a sketch in full-screen,
\ -accessible from the Sketch menu. +选择背景颜色当使用展示模式时.
\ +展示模式通常被用来在全屏模式下展示速写程序,
\ +可从速写本菜单中访问. preferences.use_smooth_text = 在编辑器窗口中使用平滑字体 preferences.enable_complex_text_input = 启用复杂字体输入 preferences.enable_complex_text_input_example = i.e. Japanese @@ -141,70 +141,70 @@ preferences.trigger_with = Trigger with preferences.cmd_space = space preferences.increase_max_memory = 增加最大内存至 preferences.delete_previous_folder_on_export = 当导出时删除先前的文件夹 -preferences.hide_toolbar_background_image = Hide tab/toolbar background image -preferences.check_for_updates_on_startup = Check for updates on startup +preferences.hide_toolbar_background_image = 隐藏标签/工具栏背景图片 +preferences.check_for_updates_on_startup = 在启动时检查有无更新 preferences.run_sketches_on_display = Run sketches on display preferences.run_sketches_on_display.tip = \ Sets the display where sketches are initially placed.
\ As usual, if the sketch window is moved, it will re-open
\ at the same location, however when running in present
\ (full screen) mode, this display will always be used. -preferences.automatically_associate_pde_files = Automatically associate .pde files with Processing +preferences.automatically_associate_pde_files = 自动关联 .pde 文件通过 Processing preferences.launch_programs_in = Launch programs in -preferences.launch_programs_in.mode = mode -preferences.file = More preferences can be edited directly in the file -preferences.file.hint = edit only when Processing is not running +preferences.launch_programs_in.mode = 模式 +preferences.file = 更多选项可直接编辑该文件 +preferences.file.hint = 请在Processing不在运行时编辑该文件 # Sketchbook Location (Frame) -sketchbook_location = Select new sketchbook location +sketchbook_location = 选择新速写本位置 # Sketchbook (Frame) sketchbook = Sketchbook sketchbook.tree = Sketchbook # examples (Frame) -examples = Examples +examples = 范例程序 # Export (Frame) -export = 导出选项 +export = 输出选项 export.platforms = 系统平台 export.options = 选项 -export.options.fullscreen = 全拼 (展示模式) +export.options.fullscreen = 全屏 (展示模式) export.options.show_stop_button = 显示停止按钮 -export.description.line1 = 为导出程序创建双击事件, +export.description.line1 = 为输出程序创建双击事件, export.description.line2 = 为所选系统创建独立运行程序. # Find (Frame) -find = Find -find.find = Find: -find.replace_with = Replace with: -find.ignore_case = Ignore Case -find.all_tabs = All Tabs +find = 搜索 +find.find = 搜索: +find.replace_with = 替换为: +find.ignore_case = 忽略大小写 +find.all_tabs = 所有标签 find.wrap_around = Wrap Around -find.btn.replace_all = Replace All -find.btn.replace = Replace -find.btn.find_and_replace = Find & Replace -find.btn.previous = Previous -find.btn.find = Find +find.btn.replace_all = 全部替换 +find.btn.replace = 替换 +find.btn.find_and_replace = 搜索 & 替换 +find.btn.previous = 上一个 +find.btn.find = 搜索 # Find in reference (Frame) -find_in_reference = Find in Reference +find_in_reference = 在参考文档中搜索 # Library Manager (Frame) -library.category = Category: -library.filter_your_search = Filter your search... +library.category = 目录: +library.filter_your_search = 筛查需找... # File (Frame) -file = Select an image or other data file to copy to your sketch +file = 选择一个图片或其它文件拷贝至你的速写本中 # Create Font (Frame) -create_font = Create Font +create_font = 创建字体 # Color Selector (Frame) -color_selector = Color Selector +color_selector = 颜色选择 # Archive Sketch (Frame) -archive_sketch = Archive sketch as... +archive_sketch = 速写本压缩输出... # --------------------------------------- @@ -225,11 +225,11 @@ toolbar.add_mode = 添加模式... # Editor # [Tab1] [Tab2] [v] -editor.header.new_tab = 新建Tab +editor.header.new_tab = 新建标签 editor.header.rename = 重命名 editor.header.delete = 删除 -editor.header.previous_tab = 前一个Tab -editor.header.next_tab = 后一个Tab +editor.header.previous_tab = 前一个标签 +editor.header.next_tab = 后一个标签 editor.header.delete.warning.title = Yeah, no. editor.header.delete.warning.text = You can't delete the last tab of the last open sketch. @@ -267,7 +267,7 @@ contrib.install = 安装 contrib.progress.starting = 开始 contrib.progress.downloading = 下载 contrib.download_error = 下载时出现问题. -contrib.unsupported_operating_system = 你当前的操作系统似乎不被自持. 你应该访问 %s's 该库文件地址得到更多信息. +contrib.unsupported_operating_system = 你当前的操作系统似乎不被支持. 你应该访问 %s's 该库文件地址得到更多信息. # --------------------------------------- From 51c97ddfd95c499b2373c45d2142564fafb347ad Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 13 Aug 2014 13:56:23 -0400 Subject: [PATCH 06/27] Modified the change detection to only prompt for a reload if the changed file is in the sketch or the file was changed in gedit --- app/src/processing/app/Editor.java | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index cd1588ae6..30fe47c44 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2428,8 +2428,27 @@ public abstract class Editor extends JFrame implements RunnerListener { //due to some weird shit, if a file was editted in gedit, the context is .goutputstream-XXXXX //this makes things.... complicated //System.out.println(e.context()); - + System.out.println(e.context()); + boolean openedFile = false; + if (((Path)e.context()).getFileName().toString().startsWith(".goutputstream")){ + openedFile = true; + } + if (!openedFile) { + for (SketchCode sc: sketch.getCode()){ + System.err.println("Code: \t\'"+sc.getFileName()+"\'\t\t\'"+e.context()+"\'"); + //if a gedit edit or an edit of one of the files in the sketch + if (sc.getFileName().equals(((Path)e.context()).getFileName().toString())){ + openedFile = true; + break; + } + } + } + //if the file is not open in the sketch, then don't ask to reload + if(!openedFile){ + continue; + } + //if we already reloaded in this cycle, then don't reload again if (didReload){ break; From 8f8906686bed4786a76d03cf11209154f6c580e7 Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 13 Aug 2014 13:56:23 -0400 Subject: [PATCH 07/27] Modified the change detection to only prompt for a reload if the changed file is in the sketch or the file was changed in gedit --- app/src/processing/app/Editor.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index cd1588ae6..98787212a 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2428,8 +2428,25 @@ public abstract class Editor extends JFrame implements RunnerListener { //due to some weird shit, if a file was editted in gedit, the context is .goutputstream-XXXXX //this makes things.... complicated //System.out.println(e.context()); - + boolean openedFile = false; + if (((Path)e.context()).getFileName().toString().startsWith(".goutputstream")){ + openedFile = true; + } + if (!openedFile) { + for (SketchCode sc: sketch.getCode()){ + //if a gedit edit or an edit of one of the files in the sketch + if (sc.getFileName().equals(((Path)e.context()).getFileName().toString())){ + openedFile = true; + break; + } + } + } + //if the file is not open in the sketch, then don't ask to reload + if(!openedFile){ + continue; + } + //if we already reloaded in this cycle, then don't reload again if (didReload){ break; From ead108710108908d0068dcb544802042b873da8d Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 13 Aug 2014 14:03:57 -0400 Subject: [PATCH 08/27] Removed print statements --- app/src/processing/app/Editor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 30fe47c44..e3d82fd43 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2429,14 +2429,14 @@ public abstract class Editor extends JFrame implements RunnerListener { //this makes things.... complicated //System.out.println(e.context()); - System.out.println(e.context()); + //System.out.println(e.context()); boolean openedFile = false; if (((Path)e.context()).getFileName().toString().startsWith(".goutputstream")){ openedFile = true; } if (!openedFile) { for (SketchCode sc: sketch.getCode()){ - System.err.println("Code: \t\'"+sc.getFileName()+"\'\t\t\'"+e.context()+"\'"); + //System.err.println("Code: \t\'"+sc.getFileName()+"\'\t\t\'"+e.context()+"\'"); //if a gedit edit or an edit of one of the files in the sketch if (sc.getFileName().equals(((Path)e.context()).getFileName().toString())){ openedFile = true; From cfcd938f3df973c354c00496e09064e1e1c1071e Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 13 Aug 2014 14:11:58 -0400 Subject: [PATCH 09/27] Changed wording to be more clear what is being watched by the process --- app/src/processing/app/Editor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index e3d82fd43..4c2fe1844 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2459,7 +2459,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // Path path = root.resolve(p); int response = Base .showYesNoQuestion(Editor.this, "File Modified", - "A file has been modified externally", + "Your sketch has been modified externally", "Would you like to reload the sketch?"); if (response == 0) { //reload the sketch From 43e123d925a5d35ddc9af92328121b89cb82940c Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Tue, 12 Aug 2014 01:11:10 +0530 Subject: [PATCH 10/27] Fixed Contributions Managers not showing due to MissingResourceException --- .../app/contrib/ContributionManagerDialog.java | 13 +++++++++++-- app/src/processing/app/languages/PDE.properties | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 82d4d79ad..30c2a4fe0 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -44,6 +44,7 @@ public class ContributionManagerDialog { static final String ANY_CATEGORY = Language.text("contrib.all"); JFrame dialog; + String title; ContributionFilter filter; JComboBox categoryChooser; JScrollPane scrollPane; @@ -60,8 +61,16 @@ public class ContributionManagerDialog { public ContributionManagerDialog(ContributionType type) { if (type == null) { + title = Language.text("contrib.manager_title.update"); filter = ContributionType.createUpdateFilter(); } else { + if (type == ContributionType.MODE) + title = Language.text("contrib.manager_title.mode"); + else if (type == ContributionType.TOOL) + title = Language.text("contrib.manager_title.tool"); + else if (type == ContributionType.LIBRARY) + title = Language.text("contrib.manager_title.library"); + filter = type.createFilter(); } contribListing = ContributionListing.getInstance(); @@ -83,7 +92,7 @@ public class ContributionManagerDialog { this.editor = editor; if (dialog == null) { - dialog = new JFrame(Language.text("contrib")); + dialog = new JFrame(title); restartButton = new JButton(Language.text("contrib.restart")); restartButton.setVisible(false); @@ -97,7 +106,7 @@ public class ContributionManagerDialog { Editor ed = iter.next(); if (ed.getSketch().isModified()) { int option = Base - .showYesNoQuestion(editor, Language.text("contrib"), + .showYesNoQuestion(editor, title, Language.text("contrib.unsaved_changes"), Language.text("contrib.unsaved_changes.prompt")); diff --git a/app/src/processing/app/languages/PDE.properties b/app/src/processing/app/languages/PDE.properties index fa80b739d..2fa24402f 100644 --- a/app/src/processing/app/languages/PDE.properties +++ b/app/src/processing/app/languages/PDE.properties @@ -259,6 +259,10 @@ editor.status.printing.canceled = Printing canceled. # Contribution Panel contrib = Contribution Manager +contrib.manager_title.update = Update Manager +contrib.manager_title.mode = Mode Manager +contrib.manager_title.tool = Tool Manager +contrib.manager_title.library = Library Manager contrib.category = Category: contrib.filter_your_search = Filter your search... contrib.restart = Restart Processing From cddf39bed96f09c9fdb55eb2b8fe0558d785aa32 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 14 Aug 2014 12:11:21 -0400 Subject: [PATCH 11/27] Added CREATE and DELETE listeners and modified the detection to request a reload with any file type recognized by the current mode. As a result of adding delete it attempts to verify that you're not deleting the last code-file in your sketch, if you are, then it tries to re-save the SketchCode. Also had to modify EditorHeader to prevent the reload popup from appearing with internal deletes or creates --- app/src/processing/app/Editor.java | 134 +++++++++++++---------- app/src/processing/app/EditorHeader.java | 5 + 2 files changed, 80 insertions(+), 59 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 4c2fe1844..c0e066d96 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2354,26 +2354,30 @@ public abstract class Editor extends JFrame implements RunnerListener { } //set to true when the sketch is saved from inside processing - private boolean saved; + private boolean changed; + + //used to prevent the fileChangeListener from asking for reloads after internal changes + public void setChanged() { + changed = true; + } - private boolean didReload; - //TODO set to the appropriate value private boolean reloadEnabled = true; - + //the key which is being used to poll the fs for changes private WatchKey key = null; private void initFileChangeListener() { - if(!reloadEnabled){ + if (!reloadEnabled) { return; } try { WatchService watchService = FileSystems.getDefault().newWatchService(); - key = sketch.getFolder().toPath() - .register(watchService, -// StandardWatchEventKinds.ENTRY_CREATE, -// StandardWatchEventKinds.ENTRY_DELETE, + key = sketch + .getFolder() + .toPath() + .register(watchService, StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); } catch (IOException e) { //registring the watch failed, ignore it @@ -2381,11 +2385,15 @@ public abstract class Editor extends JFrame implements RunnerListener { final WatchKey finKey = key; - //if the key is null for some reason, don't bother attaching a listener to it, they can deal without one + //if the key is null for some reason, don't bother attaching a listener to it if (finKey != null) { WindowFocusListener fl = new WindowFocusListener() { @Override public void windowGainedFocus(WindowEvent arg0) { + //we switched locations (saveAs), ignore old things + if (key != finKey) { + return; + } if (!reloadEnabled) { return; } @@ -2393,24 +2401,28 @@ public abstract class Editor extends JFrame implements RunnerListener { if (!finKey.isValid()) { return; } - + List> events = finKey.pollEvents(); - processFileEvents(events); + if (!changed) + processFileEvents(events); } @Override - public void windowLostFocus(WindowEvent arg0){ + public void windowLostFocus(WindowEvent arg0) { + //we switched locations (saveAs), ignore old things + if (key != finKey) { + return; + } List> events = finKey.pollEvents(); //don't ask to reload a file we saved - if(!saved){ + if (!changed) { processFileEvents(events); } - saved = false; + changed = false; } }; //the key can now be polled for changes in the files this.addWindowFocusListener(fl); - } } @@ -2422,60 +2434,62 @@ public abstract class Editor extends JFrame implements RunnerListener { * (sketch.getFolder()) */ private void processFileEvents(List> events) { - didReload = false; for (WatchEvent e : events) { - //the context is the name of the file inside the path - //due to some weird shit, if a file was editted in gedit, the context is .goutputstream-XXXXX - //this makes things.... complicated - //System.out.println(e.context()); - - //System.out.println(e.context()); - boolean openedFile = false; - if (((Path)e.context()).getFileName().toString().startsWith(".goutputstream")){ - openedFile = true; - } - if (!openedFile) { - for (SketchCode sc: sketch.getCode()){ - //System.err.println("Code: \t\'"+sc.getFileName()+"\'\t\t\'"+e.context()+"\'"); - //if a gedit edit or an edit of one of the files in the sketch - if (sc.getFileName().equals(((Path)e.context()).getFileName().toString())){ - openedFile = true; - break; - } + boolean sketchFile = false; + Path file = ((Path) e.context()).getFileName(); + for (String s : getMode().getExtensions()) { + //if it is a change to a file with a known extension + if (file.toString().endsWith(s)) { + sketchFile = true; + break; } } - //if the file is not open in the sketch, then don't ask to reload - if(!openedFile){ + //if the file is not a known type, then go the the next event + if (!sketchFile) { continue; } - - //if we already reloaded in this cycle, then don't reload again - if (didReload){ - break; - } - if (e.kind().equals(StandardWatchEventKinds.ENTRY_MODIFY)) { -// Path p = (Path) e.context(); -// Path root = (Path) key.watchable(); -// Path path = root.resolve(p); - int response = Base - .showYesNoQuestion(Editor.this, "File Modified", - "Your sketch has been modified externally", - "Would you like to reload the sketch?"); - if (response == 0) { - //reload the sketch + + int response = Base + .showYesNoQuestion(Editor.this, + "File Modified", + "Your sketch has been modified externally", + "Would you like to reload the sketch?"); + if (response == 0) { + //grab the 'main' code in case this reload tries to delete everything + File sc = sketch.getMainFile(); + //reload the sketch + try { sketch.reload(); header.rebuild(); - didReload = true; + } catch (Exception f) { + if (sketch.getCodeCount() < 1) { + Base + .showWarning("Canceling Reload", + "You cannot delete the last code file in a sketch!"); + //if they deleted the last file, re-save the SketchCode + try { + //make a blank file + sc.createNewFile(); + } catch (IOException e1) { + //if that didn't work, tell them it's un-recoverable + Base.showError("Reload failed", + "The sketch contians no code files", e1); + //don't try to reload again after the double fail + //this editor is probably trashed by this point, but a save-as might be possible + break; + } + //don't ask for another reload after this save + changed = true; + return; + } } - } else { - //called when a file is created or deleted - //for now, do nothing + //now that we've reloaded once, don't try to reload again + break; } } - saved = false; + changed = false; } - /** * Set the title of the PDE window based on the current sketch, i.e. * something like "sketch_070752a - Processing 0126" @@ -2506,7 +2520,7 @@ public abstract class Editor extends JFrame implements RunnerListener { public boolean handleSave(boolean immediately) { // handleStop(); // 0136 - saved = true; + setChanged(); if (sketch.isUntitled()) { return handleSaveAs(); // need to get the name, user might also cancel here @@ -2550,6 +2564,8 @@ public abstract class Editor extends JFrame implements RunnerListener { statusNotice("Saving..."); try { if (sketch.saveAs()) { + //a saveAs moves where the files are, so a listener must be attached to the new location + initFileChangeListener(); statusNotice("Done Saving."); // Disabling this for 0125, instead rebuild the menu inside // the Save As method of the Sketch object, since that's the diff --git a/app/src/processing/app/EditorHeader.java b/app/src/processing/app/EditorHeader.java index 334d0e91d..fb70beb73 100644 --- a/app/src/processing/app/EditorHeader.java +++ b/app/src/processing/app/EditorHeader.java @@ -511,6 +511,8 @@ public class EditorHeader extends JComponent { item = Toolkit.newJMenuItemShift("New Tab", 'N'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + //prevent reload request + editor.setChanged(); editor.getSketch().handleNewCode(); } }); @@ -533,6 +535,7 @@ public class EditorHeader extends JComponent { item = new JMenuItem("Delete"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + System.out.println("here high"); Sketch sketch = editor.getSketch(); if (!Base.isMacOS() && // ok on OS X editor.base.editors.size() == 1 && // mmm! accessor @@ -542,6 +545,8 @@ public class EditorHeader extends JComponent { "of the last open sketch.", null); } else { editor.getSketch().handleDeleteCode(); + //prevent reload request + editor.setChanged(); } } }); From 7e28e1a745f59e0aacbab740aa5ba4e0edb7e4d5 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 14 Aug 2014 13:27:40 -0400 Subject: [PATCH 12/27] removed changes --- app/src/processing/app/Editor.java | 6 ------ app/src/processing/app/EditorHeader.java | 4 ---- 2 files changed, 10 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 1736f063c..1b07acb97 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2563,16 +2563,10 @@ public abstract class Editor extends JFrame implements RunnerListener { statusNotice(Language.text("editor.status.saving")); try { if (sketch.saveAs()) { -<<<<<<< HEAD - //a saveAs moves where the files are, so a listener must be attached to the new location - initFileChangeListener(); - statusNotice("Done Saving."); -======= // statusNotice("Done Saving."); // status is now printed from Sketch so that "Done Saving." // is only printed after Save As when progress bar is shown. ->>>>>>> upstream/master // Disabling this for 0125, instead rebuild the menu inside // the Save As method of the Sketch object, since that's the // only one who knows whether something was renamed. diff --git a/app/src/processing/app/EditorHeader.java b/app/src/processing/app/EditorHeader.java index f4ac4a30f..f951c0809 100644 --- a/app/src/processing/app/EditorHeader.java +++ b/app/src/processing/app/EditorHeader.java @@ -511,8 +511,6 @@ public class EditorHeader extends JComponent { item = Toolkit.newJMenuItemShift(Language.text("editor.header.new_tab"), 'N'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - //prevent reload request - editor.setChanged(); editor.getSketch().handleNewCode(); } }); @@ -544,8 +542,6 @@ public class EditorHeader extends JComponent { Language.text("editor.header.delete.warning.text"), null); } else { editor.getSketch().handleDeleteCode(); - //prevent reload request - editor.setChanged(); } } }); From f547cae7ce9ca2cf0db23e34b653c0244a38f58d Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 14 Aug 2014 13:44:01 -0400 Subject: [PATCH 13/27] Fixed merge conflicts --- app/src/processing/app/Editor.java | 105 +++++++++++++++-------- app/src/processing/app/EditorHeader.java | 3 +- 2 files changed, 73 insertions(+), 35 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 1b07acb97..c203dec93 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2396,34 +2396,42 @@ public abstract class Editor extends JFrame implements RunnerListener { // } } + //used to prevent the fileChangeListener from asking for reloads after internal changes + public void setWatcherSave() { + watcherSave = true; + } + //set to true when the sketch is saved from inside processing private boolean watcherSave; - private boolean watcherReloaded; - + //the key which is being used to poll the fs for changes private WatchKey watcherKey = null; private void initFileChangeListener() { try { WatchService watchService = FileSystems.getDefault().newWatchService(); - Path folderPath = sketch.getFolder().toPath(); - watcherKey = folderPath.register(watchService, -// StandardWatchEventKinds.ENTRY_CREATE, -// StandardWatchEventKinds.ENTRY_DELETE, - StandardWatchEventKinds.ENTRY_MODIFY); + watcherKey = sketch + .getFolder() + .toPath() + .register(watchService, StandardWatchEventKinds.ENTRY_CREATE, + StandardWatchEventKinds.ENTRY_DELETE, + StandardWatchEventKinds.ENTRY_MODIFY); } catch (IOException e) { e.printStackTrace(); } final WatchKey finKey = watcherKey; - // if the key is null for some reason, don't bother attaching - // a listener to it, they can deal without one + //if the key is null for some reason, don't bother attaching a listener to it if (finKey != null) { // the key can now be polled for changes in the files addWindowFocusListener(new WindowFocusListener() { @Override public void windowGainedFocus(WindowEvent arg0) { + //we switched locations (saveAs), ignore old things + if (watcherKey != finKey) { + return; + } // check preference here for enabled or not? //if the directory was deleted, then don't scan @@ -2431,12 +2439,16 @@ public abstract class Editor extends JFrame implements RunnerListener { List> events = finKey.pollEvents(); processFileEvents(events); } + + List> events = finKey.pollEvents(); + if (!watcherSave) + processFileEvents(events); } @Override public void windowLostFocus(WindowEvent arg0) { //we switched locations (saveAs), ignore old things - if (key != finKey) { + if (watcherKey != finKey) { return; } List> events = finKey.pollEvents(); @@ -2456,34 +2468,57 @@ public abstract class Editor extends JFrame implements RunnerListener { * @param events the list of events that have occured in the sketch folder */ private void processFileEvents(List> events) { - watcherReloaded = false; for (WatchEvent e : events) { - //the context is the name of the file inside the path - //due to some weird shit, if a file was editted in gedit, the context is .goutputstream-XXXXX - //this makes things.... complicated - //System.out.println(e.context()); - - //if we already reloaded in this cycle, then don't reload again - if (watcherReloaded){ - break; + boolean sketchFile = false; + Path file = ((Path) e.context()).getFileName(); + for (String s : getMode().getExtensions()) { + //if it is a change to a file with a known extension + if (file.toString().endsWith(s)) { + sketchFile = true; + break; + } } - if (e.kind().equals(StandardWatchEventKinds.ENTRY_MODIFY)) { -// Path p = (Path) e.context(); -// Path root = (Path) key.watchable(); -// Path path = root.resolve(p); - int response = - Base.showYesNoQuestion(Editor.this, "File Modified", - "A file has been modified externally", - "Would you like to reload the sketch?"); - if (response == 0) { - // reload the sketch + //if the file is not a known type, then go the the next event + if (!sketchFile) { + continue; + } + + int response = Base + .showYesNoQuestion(Editor.this, + "File Modified", + "Your sketch has been modified externally", + "Would you like to reload the sketch?"); + if (response == 0) { + //grab the 'main' code in case this reload tries to delete everything + File sc = sketch.getMainFile(); + //reload the sketch + try { sketch.reload(); header.rebuild(); - watcherReloaded = true; + } catch (Exception f) { + if (sketch.getCodeCount() < 1) { + Base + .showWarning("Canceling Reload", + "You cannot delete the last code file in a sketch!"); + //if they deleted the last file, re-save the SketchCode + try { + //make a blank file + sc.createNewFile(); + } catch (IOException e1) { + //if that didn't work, tell them it's un-recoverable + Base.showError("Reload failed", + "The sketch contians no code files", e1); + //don't try to reload again after the double fail + //this editor is probably trashed by this point, but a save-as might be possible + break; + } + //don't ask for another reload after this save + watcherSave = true; + return; + } } - } else { - // called when a file is created or deleted - // for now, do nothing + //now that we've reloaded once, don't try to reload again + break; } } watcherSave = false; @@ -2519,7 +2554,7 @@ public abstract class Editor extends JFrame implements RunnerListener { public boolean handleSave(boolean immediately) { // handleStop(); // 0136 - watcherSave = true; + setWatcherSave(); if (sketch.isUntitled()) { return handleSaveAs(); // need to get the name, user might also cancel here @@ -2563,6 +2598,8 @@ public abstract class Editor extends JFrame implements RunnerListener { statusNotice(Language.text("editor.status.saving")); try { if (sketch.saveAs()) { + //a saveAs moves where the files are, so a listener must be attached to the new location + initFileChangeListener(); // statusNotice("Done Saving."); // status is now printed from Sketch so that "Done Saving." // is only printed after Save As when progress bar is shown. diff --git a/app/src/processing/app/EditorHeader.java b/app/src/processing/app/EditorHeader.java index f951c0809..be1cfbebc 100644 --- a/app/src/processing/app/EditorHeader.java +++ b/app/src/processing/app/EditorHeader.java @@ -512,6 +512,7 @@ public class EditorHeader extends JComponent { item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { editor.getSketch().handleNewCode(); + editor.setWatcherSave(); } }); menu.add(item); @@ -533,7 +534,6 @@ public class EditorHeader extends JComponent { item = new JMenuItem(Language.text("editor.header.delete")); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - System.out.println("here high"); Sketch sketch = editor.getSketch(); if (!Base.isMacOS() && // ok on OS X editor.base.editors.size() == 1 && // mmm! accessor @@ -542,6 +542,7 @@ public class EditorHeader extends JComponent { Language.text("editor.header.delete.warning.text"), null); } else { editor.getSketch().handleDeleteCode(); + editor.setWatcherSave(); } } }); From 66ce5e43f7ba6f1e68b5f91396a5727c6900991f Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sun, 27 Jul 2014 00:11:40 +0400 Subject: [PATCH 14/27] Added new 'example' type in ContributionType.java's enum --- app/src/processing/app/Base.java | 17 +++++++++++++++++ .../app/contrib/ContributionManagerDialog.java | 1 + .../app/contrib/ContributionType.java | 17 ++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index ff6ac2621..a28db5f36 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -98,6 +98,7 @@ public class Base { ContributionManagerDialog libraryManagerFrame; ContributionManagerDialog toolManagerFrame; ContributionManagerDialog modeManagerFrame; + ContributionManagerDialog exampleManagerFrame; ContributionManagerDialog updateManagerFrame; // set to true after the first time the menu is built. @@ -385,6 +386,8 @@ public class Base { new ContributionManagerDialog(ContributionType.TOOL); modeManagerFrame = new ContributionManagerDialog(ContributionType.MODE); + exampleManagerFrame = + new ContributionManagerDialog(ContributionType.EXAMPLE); updateManagerFrame = new ContributionManagerDialog(null); @@ -1651,6 +1654,14 @@ public class Base { } + /** + * Show the examples installer window. + */ + public void handleOpenExampleManager() { + exampleManagerFrame.showFrame(activeEditor); + } + + public void handleShowUpdates() { updateManagerFrame.showFrame(activeEditor); } @@ -1923,6 +1934,7 @@ public class Base { getSketchbookLibrariesFolder().mkdir(); getSketchbookToolsFolder().mkdir(); getSketchbookModesFolder().mkdir(); + getSketchbookExamplesFolder().mkdir(); // System.err.println("sketchbook: " + sketchbookFolder); } @@ -1954,6 +1966,11 @@ public class Base { } + static public File getSketchbookExamplesFolder() { + return new File(sketchbookFolder, "examples"); + } + + static protected File getDefaultSketchbookFolder() { File sketchbookFolder = null; try { diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 82d4d79ad..7bcace976 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -62,6 +62,7 @@ public class ContributionManagerDialog { if (type == null) { filter = ContributionType.createUpdateFilter(); } else { + filter = type.createFilter(); } contribListing = ContributionListing.getInstance(); diff --git a/app/src/processing/app/contrib/ContributionType.java b/app/src/processing/app/contrib/ContributionType.java index 8b882ee59..fca4f4dfb 100644 --- a/app/src/processing/app/contrib/ContributionType.java +++ b/app/src/processing/app/contrib/ContributionType.java @@ -31,7 +31,7 @@ import processing.app.Editor; import processing.app.Library; public enum ContributionType { - LIBRARY, TOOL, MODE; + LIBRARY, TOOL, MODE, EXAMPLE; public String toString() { @@ -42,6 +42,8 @@ public enum ContributionType { return "tool"; case MODE: return "mode"; + case EXAMPLE: + return "example"; } return null; // should be unreachable }; @@ -65,6 +67,8 @@ public enum ContributionType { return "tools"; case MODE: return "modes"; + case EXAMPLE: + return "examples"; } return null; // should be unreachable } @@ -106,6 +110,9 @@ public enum ContributionType { if ("mode".equalsIgnoreCase(s)) { return MODE; } + if ("example".equalsIgnoreCase(s)) { + return EXAMPLE; + } } return null; } @@ -119,6 +126,8 @@ public enum ContributionType { return Base.getSketchbookToolsFolder(); case MODE: return Base.getSketchbookModesFolder(); + case EXAMPLE: + return Base.getSketchbookExamplesFolder(); } return null; } @@ -181,6 +190,9 @@ public enum ContributionType { return ToolContribution.load(folder); case MODE: return ModeContribution.load(base, folder); + case EXAMPLE: + //TODO: Fill this in if reqd + return null; } return null; } @@ -198,6 +210,9 @@ public enum ContributionType { case MODE: contribs.addAll(editor.getBase().getModeContribs()); break; + case EXAMPLE: + //TODO: Fill this in if reqd + break; } return contribs; } From fbcf60e2ad059778dad1e0db7b6f4977e6c0f063 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Wed, 30 Jul 2014 12:29:45 +0400 Subject: [PATCH 15/27] UI of 'Add Examples...' done --- app/src/processing/app/Mode.java | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 3f669f643..61335d319 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -692,7 +692,40 @@ public abstract class Mode { } }); + JPanel examplesPanel = new JPanel(); + examplesPanel.setLayout(new BoxLayout(examplesPanel, BoxLayout.PAGE_AXIS)); + examplesPanel.setBackground(Color.WHITE); + + final JLabel openExamplesManagerLabel = new JLabel("Add Example..."); + openExamplesManagerLabel.setOpaque(false); + openExamplesManagerLabel.setBorder(new EmptyBorder(10, 6, 1, 5)); + openExamplesManagerLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + openExamplesManagerLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + openExamplesManagerLabel.setForeground(new Color(0, 0, 238)); + openExamplesManagerLabel.addMouseListener(new MouseListener() { + + @Override + public void mouseReleased(MouseEvent e) {} + + @Override + public void mousePressed(MouseEvent e) {} + + @Override + public void mouseExited(MouseEvent e) {} + + @Override + public void mouseEntered(MouseEvent e) {} + + @Override + public void mouseClicked(MouseEvent e) { + base.handleOpenExampleManager(); + openExamplesManagerLabel.setForeground(new Color(85, 26, 139)); + } + }); + final JTree tree = buildExamplesTree(); + tree.setOpaque(true); + tree.setAlignmentX(Component.LEFT_ALIGNMENT); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.setShowsRootHandles(true); @@ -763,7 +796,12 @@ public abstract class Mode { JScrollPane treePane = new JScrollPane(tree); treePane.setPreferredSize(new Dimension(250, 450)); treePane.setBorder(new EmptyBorder(0, 0, 0, 0)); - examplesFrame.getContentPane().add(treePane); + treePane.setOpaque(true); + treePane.setAlignmentX(Component.LEFT_ALIGNMENT); + + examplesPanel.add(openExamplesManagerLabel); + examplesPanel.add(treePane); + examplesFrame.getContentPane().add(examplesPanel); examplesFrame.pack(); restoreExpanded(tree); From 31a85c7c8ffe7f403f74ef66ad5b7e5f23c8085b Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Wed, 30 Jul 2014 19:39:49 +0400 Subject: [PATCH 16/27] Contributed Examples tree displays in Examples window Also, example folder does not show as node in JTree --- app/src/processing/app/Mode.java | 213 ++++++++++++++++++++----------- 1 file changed, 142 insertions(+), 71 deletions(-) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 61335d319..7b1a889ed 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -69,6 +69,8 @@ public abstract class Mode { protected File examplesFolder; protected File librariesFolder; protected File referenceFolder; + + protected File examplesContribFolder; public ArrayList coreLibraries; public ArrayList contribLibraries; @@ -100,6 +102,9 @@ public abstract class Mode { examplesFolder = new File(folder, "examples"); librariesFolder = new File(folder, "libraries"); referenceFolder = new File(folder, "reference"); + + // Get path to the contributed examples compatible with this mode + examplesContribFolder = Base.getSketchbookExamplesFolder(); // rebuildToolbarMenu(); rebuildLibraryList(); @@ -588,6 +593,15 @@ public abstract class Mode { } + public File[] getContributedExampleCategoryFolders() { + return examplesContribFolder.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return dir.isDirectory() && name.charAt(0) != '.'; + } + }); + } + + public JTree buildExamplesTree() { DefaultMutableTreeNode node = new DefaultMutableTreeNode("Examples"); @@ -665,6 +679,40 @@ public abstract class Mode { } + public JTree buildContributedExamplesTrees() { + DefaultMutableTreeNode node = new DefaultMutableTreeNode("Contributed Examples"); + + JTree examplesTree = new JTree(node); + + try { + // break down the examples folder for examples + File[] subfolders = getContributedExampleCategoryFolders(); + + for (File sub : subfolders) { + DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); + if (base.addSketches(subNode, sub)) { + node.add(subNode); + int exampleNodeNumber = -1; + for (int y = 0; y < subNode.getChildCount(); y++) + if (subNode.getChildAt(y).toString().equals("example")) + exampleNodeNumber = y; + if (exampleNodeNumber == -1) + continue; + TreeNode exampleNode = subNode.getChildAt(exampleNodeNumber); + subNode.remove(exampleNodeNumber); + int count = exampleNode.getChildCount(); + for (int x = 0; x < count; x++) { + subNode.add((DefaultMutableTreeNode) exampleNode.getChildAt(0)); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return examplesTree; + } + + public void resetExamples() { if (examplesFrame != null) { boolean visible = examplesFrame.isVisible(); @@ -724,83 +772,34 @@ public abstract class Mode { }); final JTree tree = buildExamplesTree(); - tree.setOpaque(true); - tree.setAlignmentX(Component.LEFT_ALIGNMENT); - - tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - tree.setShowsRootHandles(true); -// tree.setToggleClickCount(2); - // expand the root - tree.expandRow(0); - // now hide the root - tree.setRootVisible(false); - - // After 2.0a7, no longer expanding each of the categories at Casey's - // request. He felt that the window was too complicated too quickly. -// for (int row = tree.getRowCount()-1; row >= 0; --row) { -// tree.expandRow(row); -// } - - tree.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); - - int selRow = tree.getRowForLocation(e.getX(), e.getY()); - //TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); - //if (node != null && node.isLeaf() && node.getPath().equals(selPath)) { - if (node != null && node.isLeaf() && selRow != -1) { - SketchReference sketch = (SketchReference) node.getUserObject(); - base.handleOpen(sketch.getPath()); - } - } - } - }); - tree.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { // doesn't fire keyTyped() - examplesFrame.setVisible(false); - } - } - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); - if (node != null && node.isLeaf()) { - SketchReference sketch = (SketchReference) node.getUserObject(); - base.handleOpen(sketch.getPath()); - } - } - } - }); - - tree.addTreeExpansionListener(new TreeExpansionListener() { - @Override - public void treeExpanded(TreeExpansionEvent event) { - updateExpanded(tree); - } - - @Override - public void treeCollapsed(TreeExpansionEvent event) { - updateExpanded(tree); - } - }); - - tree.setBorder(new EmptyBorder(5, 5, 5, 5)); - if (Base.isMacOS()) { - tree.setToggleClickCount(2); - } else { - tree.setToggleClickCount(1); - } + setupExamplesTree(tree); + JScrollPane treePane = new JScrollPane(tree); - treePane.setPreferredSize(new Dimension(250, 450)); - treePane.setBorder(new EmptyBorder(0, 0, 0, 0)); + treePane.setPreferredSize(new Dimension(250, 300)); + treePane.setBorder(new EmptyBorder(5, 0, 0, 0)); treePane.setOpaque(true); + treePane.setBackground(Color.WHITE); treePane.setAlignmentX(Component.LEFT_ALIGNMENT); + JLabel contribExLabel = new JLabel("Contributed Examples"); + contribExLabel.setOpaque(false); + contribExLabel.setBorder(new EmptyBorder(10, 6, 1, 5)); + contribExLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + + final JTree tree2 = buildContributedExamplesTrees(); + setupExamplesTree(tree2); + + JScrollPane treePane2 = new JScrollPane(tree2); + treePane2.setPreferredSize(new Dimension(250, 300)); + treePane2.setBorder(new EmptyBorder(0, 0, 10, 0)); + treePane2.setOpaque(true); + treePane2.setBackground(Color.WHITE); + treePane2.setAlignmentX(Component.LEFT_ALIGNMENT); + examplesPanel.add(openExamplesManagerLabel); examplesPanel.add(treePane); + examplesPanel.add(contribExLabel); + examplesPanel.add(treePane2); examplesFrame.getContentPane().add(examplesPanel); examplesFrame.pack(); @@ -823,6 +822,78 @@ public abstract class Mode { } + private void setupExamplesTree(final JTree tree) { + tree.setOpaque(true); + tree.setAlignmentX(Component.LEFT_ALIGNMENT); + + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.setShowsRootHandles(true); +// tree.setToggleClickCount(2); + // expand the root + tree.expandRow(0); + // now hide the root + tree.setRootVisible(false); + + // After 2.0a7, no longer expanding each of the categories at Casey's + // request. He felt that the window was too complicated too quickly. +// for (int row = tree.getRowCount()-1; row >= 0; --row) { +// tree.expandRow(row); +// } + + tree.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); + + int selRow = tree.getRowForLocation(e.getX(), e.getY()); + //TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); + //if (node != null && node.isLeaf() && node.getPath().equals(selPath)) { + if (node != null && node.isLeaf() && selRow != -1) { + SketchReference sketch = (SketchReference) node.getUserObject(); + base.handleOpen(sketch.getPath()); + } + } + } + }); + tree.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { // doesn't fire keyTyped() + examplesFrame.setVisible(false); + } + } + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); + if (node != null && node.isLeaf()) { + SketchReference sketch = (SketchReference) node.getUserObject(); + base.handleOpen(sketch.getPath()); + } + } + } + }); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + @Override + public void treeExpanded(TreeExpansionEvent event) { + updateExpanded(tree); + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + updateExpanded(tree); + } + }); + + tree.setBorder(new EmptyBorder(5, 5, 5, 5)); + if (Base.isMacOS()) { + tree.setToggleClickCount(2); + } else { + tree.setToggleClickCount(1); + } + } + protected void updateExpanded(JTree tree) { Enumeration en = tree.getExpandedDescendants(new TreePath(tree.getModel().getRoot())); //en.nextElement(); // skip the root "Examples" node From 31aa89f35cf74889774af425b3602971bab60af9 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sat, 2 Aug 2014 15:51:31 +0530 Subject: [PATCH 17/27] Contribs now show in Example Manager --- app/src/processing/app/Base.java | 22 +++++++++ app/src/processing/app/Mode.java | 17 ++----- .../contrib/ContributionManagerDialog.java | 5 +- .../app/contrib/ContributionType.java | 7 ++- .../app/contrib/ExampleContribution.java | 46 +++++++++++++++++++ 5 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 app/src/processing/app/contrib/ExampleContribution.java diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index a28db5f36..e1df82070 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -124,6 +124,8 @@ public class Base { private Mode[] coreModes; //public List contribModes; protected ArrayList modeContribs; + + protected ArrayList exampleContribs; private JMenu sketchbookMenu; @@ -340,6 +342,19 @@ public class Base { } + /** + * Instantiates and adds new contributed modes to the contribModes list. + * Checks for duplicates so the same mode isn't instantiates twice. Does not + * remove modes because modes can't be removed once they are instantiated. + */ + void rebuildContribExamples() { + if (exampleContribs == null) { + exampleContribs = new ArrayList(); + } + ExampleContribution.loadMissing(this); + } + + public Base(String[] args) throws Exception { // // Get the sketchbook path, and make sure it's set properly // determineSketchbookFolder(); @@ -357,6 +372,8 @@ public class Base { ContributionManager.cleanup(this); buildCoreModes(); rebuildContribModes(); + + rebuildContribExamples(); // Needs to happen after the sketchbook folder has been located. // Also relies on the modes to be loaded so it knows what can be @@ -661,6 +678,11 @@ public class Base { } + public ArrayList getExampleContribs() { + return exampleContribs; + } + + // Because of variations in native windowing systems, no guarantees about // changes to the focused and active Windows can be made. Developers must // never assume that this Window is the focused or active Window until this diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 7b1a889ed..511c45bae 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -34,6 +34,7 @@ import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; import javax.swing.tree.*; +import processing.app.contrib.ContributionType; import processing.app.syntax.*; import processing.core.PApplet; @@ -593,15 +594,6 @@ public abstract class Mode { } - public File[] getContributedExampleCategoryFolders() { - return examplesContribFolder.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return dir.isDirectory() && name.charAt(0) != '.'; - } - }); - } - - public JTree buildExamplesTree() { DefaultMutableTreeNode node = new DefaultMutableTreeNode("Examples"); @@ -685,9 +677,10 @@ public abstract class Mode { JTree examplesTree = new JTree(node); try { - // break down the examples folder for examples - File[] subfolders = getContributedExampleCategoryFolders(); - + File[] subfolders = ContributionType.EXAMPLE.listCandidates(examplesContribFolder); + if (subfolders == null) { + subfolders = new File[0]; //empty array + } for (File sub : subfolders) { DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); if (base.addSketches(subNode, sub)) { diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 7bcace976..64cb5da93 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -394,7 +394,10 @@ public class ContributionManagerDialog { ArrayList modes = editor.getBase().getModeContribs(); contributions.addAll(modes); - + + ArrayList examples = editor.getBase().getExampleContribs(); + contributions.addAll(examples); + // ArrayList compilations = LibraryCompilation.list(libraries); // // // Remove libraries from the list that are part of a compilations diff --git a/app/src/processing/app/contrib/ContributionType.java b/app/src/processing/app/contrib/ContributionType.java index fca4f4dfb..5e34b9d88 100644 --- a/app/src/processing/app/contrib/ContributionType.java +++ b/app/src/processing/app/contrib/ContributionType.java @@ -145,7 +145,7 @@ public enum ContributionType { * contribution type. For instance, a list of folders that have a 'mode' * subfolder if this is a ModeContribution. */ - File[] listCandidates(File folder) { + public File[] listCandidates(File folder) { return folder.listFiles(new FileFilter() { public boolean accept(File potential) { return isCandidate(potential); @@ -191,8 +191,7 @@ public enum ContributionType { case MODE: return ModeContribution.load(base, folder); case EXAMPLE: - //TODO: Fill this in if reqd - return null; + return ExampleContribution.load(folder); } return null; } @@ -211,7 +210,7 @@ public enum ContributionType { contribs.addAll(editor.getBase().getModeContribs()); break; case EXAMPLE: - //TODO: Fill this in if reqd + contribs.addAll(editor.getBase().getExampleContribs()); break; } return contribs; diff --git a/app/src/processing/app/contrib/ExampleContribution.java b/app/src/processing/app/contrib/ExampleContribution.java new file mode 100644 index 000000000..9025022db --- /dev/null +++ b/app/src/processing/app/contrib/ExampleContribution.java @@ -0,0 +1,46 @@ +package processing.app.contrib; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; + +import processing.app.Base; + +public class ExampleContribution extends LocalContribution { + + static public ExampleContribution load(File folder) { + return new ExampleContribution(folder); + } + + private ExampleContribution(File folder) { + super(folder); + } + + + static public void loadMissing(Base base) { + File examplesFolder = Base.getSketchbookExamplesFolder(); + ArrayList contribExamples = base.getExampleContribs(); + + HashMap existing = new HashMap(); + for (ExampleContribution contrib : contribExamples) { + existing.put(contrib.getFolder(), contrib); + } + File[] potential = ContributionType.EXAMPLE.listCandidates(examplesFolder); + // If modesFolder does not exist or is inaccessible (folks might like to + // mess with folders then report it as a bug) 'potential' will be null. + if (potential != null) { + for (File folder : potential) { + if (!existing.containsKey(folder)) { + contribExamples.add(new ExampleContribution(folder)); + } + } + } + } + + + @Override + public ContributionType getType() { + return ContributionType.EXAMPLE; + } + +} From 2d8098758f824ee9f07ee7f32d7310a83a084b68 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sun, 3 Aug 2014 17:42:01 +0530 Subject: [PATCH 18/27] Modes now taken into account when deciding whether to show examples --- app/src/processing/app/Mode.java | 3 ++ .../app/contrib/AvailableContribution.java | 11 ++++- .../app/contrib/ExampleContribution.java | 44 ++++++++++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 511c45bae..c6bf0a505 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -35,6 +35,7 @@ import javax.swing.event.TreeExpansionListener; import javax.swing.tree.*; import processing.app.contrib.ContributionType; +import processing.app.contrib.ExampleContribution; import processing.app.syntax.*; import processing.core.PApplet; @@ -682,6 +683,8 @@ public abstract class Mode { subfolders = new File[0]; //empty array } for (File sub : subfolders) { + if (!ExampleContribution.isExampleCompatible(base, sub)) + continue; DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); if (base.addSketches(subNode, sub)) { node.add(subNode); diff --git a/app/src/processing/app/contrib/AvailableContribution.java b/app/src/processing/app/contrib/AvailableContribution.java index 1023f2a83..e97643334 100644 --- a/app/src/processing/app/contrib/AvailableContribution.java +++ b/app/src/processing/app/contrib/AvailableContribution.java @@ -1,4 +1,4 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org @@ -268,6 +268,12 @@ class AvailableContribution extends Contribution { String prettyVersion = properties.get("prettyVersion"); if (prettyVersion == null || prettyVersion.isEmpty()) prettyVersion = getPrettyVersion(); + + String compatibleContribsList = null; + + if (getType() == ContributionType.EXAMPLE) { + compatibleContribsList = properties.get("compatibleModesList"); + } long lastUpdated; try { @@ -294,6 +300,9 @@ class AvailableContribution extends Contribution { writer.println("version=" + version); writer.println("prettyVersion=" + prettyVersion); writer.println("lastUpdated=" + lastUpdated); + if (getType() == ContributionType.EXAMPLE) { + writer.println("compatibleModesList=" + compatibleContribsList); + } writer.flush(); writer.close(); diff --git a/app/src/processing/app/contrib/ExampleContribution.java b/app/src/processing/app/contrib/ExampleContribution.java index 9025022db..e9843c15d 100644 --- a/app/src/processing/app/contrib/ExampleContribution.java +++ b/app/src/processing/app/contrib/ExampleContribution.java @@ -8,14 +8,53 @@ import processing.app.Base; public class ExampleContribution extends LocalContribution { + private ArrayList compatibleModesList; + static public ExampleContribution load(File folder) { return new ExampleContribution(folder); } private ExampleContribution(File folder) { super(folder); + compatibleModesList = parseCompatibleModesList(properties + .get("compatibleModesList")); } + private static ArrayList parseCompatibleModesList(String unparsedModes) { + ArrayList modesList = new ArrayList(); + if (unparsedModes == null || unparsedModes.isEmpty()) + return modesList; + String[] splitStr = unparsedModes.split(","); + for (String mode : splitStr) + modesList.add(mode.trim()); + return modesList; + } + + /** + * Function to determine whether or not the example present in the + * exampleLocation directory is compatible with the present mode. + * + * @param base + * @param exampleLocationFolder + * @return true if the example is compatible with the mode of the currently + * active editor + */ + public static boolean isExampleCompatible(Base base, + File exampleLocationFolder) { + File propertiesFile = new File(exampleLocationFolder, + ContributionType.EXAMPLE.toString() + + ".properties"); + if (propertiesFile.exists()) { + ArrayList compModesList = parseCompatibleModesList(Base + .readSettings(propertiesFile).get("compatibleModesList")); + for (String c : compModesList) { + if (c.equalsIgnoreCase(base.getActiveEditor().getMode().getIdentifier())) { + return true; + } + } + } + return false; + } static public void loadMissing(Base base) { File examplesFolder = Base.getSketchbookExamplesFolder(); @@ -37,10 +76,13 @@ public class ExampleContribution extends LocalContribution { } } - @Override public ContributionType getType() { return ContributionType.EXAMPLE; } + public ArrayList getCompatibleModesList() { + return compatibleModesList; + } + } From 8b913f0e635aeefdd4275f9c96ed8f48a3fe167d Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Tue, 5 Aug 2014 15:34:24 +0530 Subject: [PATCH 19/27] Updating display style of Examples Tree --- app/src/processing/app/Mode.java | 203 ++++++++---------- .../app/contrib/ExampleContribution.java | 3 +- 2 files changed, 95 insertions(+), 111 deletions(-) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index c6bf0a505..426835ba5 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -595,10 +595,10 @@ public abstract class Mode { } - public JTree buildExamplesTree() { + public DefaultMutableTreeNode buildExamplesTree() { DefaultMutableTreeNode node = new DefaultMutableTreeNode("Examples"); - JTree examplesTree = new JTree(node); +// JTree examplesTree = new JTree(node); // rebuildExamplesTree(node); // } @@ -617,30 +617,28 @@ public abstract class Mode { // }); File[] subfolders = getExampleCategoryFolders(); -// DefaultMutableTreeNode examplesParent = new DefaultMutableTreeNode("Examples"); + DefaultMutableTreeNode modeExParent = new DefaultMutableTreeNode("Mode Examples"); + for (File sub : subfolders) { DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); if (base.addSketches(subNode, sub)) { // examplesParent.add(subNode); - node.add(subNode); + modeExParent.add(subNode); } } -// node.add(examplesParent); -// examplesTree.expandPath(new TreePath(examplesParent)); - + // get library examples boolean any = false; - DefaultMutableTreeNode libParent = new DefaultMutableTreeNode("Libraries"); for (Library lib : coreLibraries) { if (lib.hasExamples()) { DefaultMutableTreeNode libNode = new DefaultMutableTreeNode(lib.getName()); - any |= base.addSketches(libNode, lib.getExamplesFolder()); - libParent.add(libNode); + if (base.addSketches(libNode, lib.getExamplesFolder())) + modeExParent.add(libNode); } } - if (any) { - node.add(libParent); - } + + if (modeExParent.getChildCount() > 0) + node.add(modeExParent); // get contrib library examples any = false; @@ -651,7 +649,7 @@ public abstract class Mode { } if (any) { // menu.addSeparator(); - DefaultMutableTreeNode contribParent = new DefaultMutableTreeNode("Contributed Libraries"); + DefaultMutableTreeNode contribParent = new DefaultMutableTreeNode("Library Examples"); // Base.addDisabledItem(menu, "Contributed"); for (Library lib : contribLibraries) { if (lib.hasExamples()) { @@ -668,15 +666,17 @@ public abstract class Mode { } catch (IOException e) { e.printStackTrace(); } - return examplesTree; + + DefaultMutableTreeNode contribExampleNode = buildContributedExamplesTrees(); + if (contribExampleNode.getChildCount() > 0) + node.add(contribExampleNode); + return node; } - public JTree buildContributedExamplesTrees() { + public DefaultMutableTreeNode buildContributedExamplesTrees() { DefaultMutableTreeNode node = new DefaultMutableTreeNode("Contributed Examples"); - JTree examplesTree = new JTree(node); - try { File[] subfolders = ContributionType.EXAMPLE.listCandidates(examplesContribFolder); if (subfolders == null) { @@ -688,6 +688,7 @@ public abstract class Mode { DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); if (base.addSketches(subNode, sub)) { node.add(subNode); + System.out.println(subNode); int exampleNodeNumber = -1; for (int y = 0; y < subNode.getChildCount(); y++) if (subNode.getChildAt(y).toString().equals("example")) @@ -699,13 +700,14 @@ public abstract class Mode { int count = exampleNode.getChildCount(); for (int x = 0; x < count; x++) { subNode.add((DefaultMutableTreeNode) exampleNode.getChildAt(0)); + System.out.println(subNode); } } } } catch (IOException e) { e.printStackTrace(); } - return examplesTree; + return node;//examplesTree; } @@ -767,8 +769,78 @@ public abstract class Mode { } }); - final JTree tree = buildExamplesTree(); - setupExamplesTree(tree); + final JTree tree = new JTree(buildExamplesTree()); + + + tree.setOpaque(true); + tree.setAlignmentX(Component.LEFT_ALIGNMENT); + + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.setShowsRootHandles(true); +// tree.setToggleClickCount(2); + // expand the root + tree.expandRow(0); + // now hide the root + tree.setRootVisible(false); + + // After 2.0a7, no longer expanding each of the categories at Casey's + // request. He felt that the window was too complicated too quickly. +// for (int row = tree.getRowCount()-1; row >= 0; --row) { +// tree.expandRow(row); +// } + + tree.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); + + int selRow = tree.getRowForLocation(e.getX(), e.getY()); + //TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); + //if (node != null && node.isLeaf() && node.getPath().equals(selPath)) { + if (node != null && node.isLeaf() && selRow != -1) { + SketchReference sketch = (SketchReference) node.getUserObject(); + base.handleOpen(sketch.getPath()); + } + } + } + }); + tree.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { // doesn't fire keyTyped() + examplesFrame.setVisible(false); + } + } + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == KeyEvent.VK_ENTER) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); + if (node != null && node.isLeaf()) { + SketchReference sketch = (SketchReference) node.getUserObject(); + base.handleOpen(sketch.getPath()); + } + } + } + }); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + @Override + public void treeExpanded(TreeExpansionEvent event) { + updateExpanded(tree); + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + updateExpanded(tree); + } + }); + + tree.setBorder(new EmptyBorder(5, 5, 5, 5)); + if (Base.isMacOS()) { + tree.setToggleClickCount(2); + } else { + tree.setToggleClickCount(1); + } JScrollPane treePane = new JScrollPane(tree); treePane.setPreferredSize(new Dimension(250, 300)); @@ -777,25 +849,8 @@ public abstract class Mode { treePane.setBackground(Color.WHITE); treePane.setAlignmentX(Component.LEFT_ALIGNMENT); - JLabel contribExLabel = new JLabel("Contributed Examples"); - contribExLabel.setOpaque(false); - contribExLabel.setBorder(new EmptyBorder(10, 6, 1, 5)); - contribExLabel.setAlignmentX(Component.LEFT_ALIGNMENT); - - final JTree tree2 = buildContributedExamplesTrees(); - setupExamplesTree(tree2); - - JScrollPane treePane2 = new JScrollPane(tree2); - treePane2.setPreferredSize(new Dimension(250, 300)); - treePane2.setBorder(new EmptyBorder(0, 0, 10, 0)); - treePane2.setOpaque(true); - treePane2.setBackground(Color.WHITE); - treePane2.setAlignmentX(Component.LEFT_ALIGNMENT); - examplesPanel.add(openExamplesManagerLabel); examplesPanel.add(treePane); - examplesPanel.add(contribExLabel); - examplesPanel.add(treePane2); examplesFrame.getContentPane().add(examplesPanel); examplesFrame.pack(); @@ -818,78 +873,6 @@ public abstract class Mode { } - private void setupExamplesTree(final JTree tree) { - tree.setOpaque(true); - tree.setAlignmentX(Component.LEFT_ALIGNMENT); - - tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - tree.setShowsRootHandles(true); -// tree.setToggleClickCount(2); - // expand the root - tree.expandRow(0); - // now hide the root - tree.setRootVisible(false); - - // After 2.0a7, no longer expanding each of the categories at Casey's - // request. He felt that the window was too complicated too quickly. -// for (int row = tree.getRowCount()-1; row >= 0; --row) { -// tree.expandRow(row); -// } - - tree.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); - - int selRow = tree.getRowForLocation(e.getX(), e.getY()); - //TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); - //if (node != null && node.isLeaf() && node.getPath().equals(selPath)) { - if (node != null && node.isLeaf() && selRow != -1) { - SketchReference sketch = (SketchReference) node.getUserObject(); - base.handleOpen(sketch.getPath()); - } - } - } - }); - tree.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { // doesn't fire keyTyped() - examplesFrame.setVisible(false); - } - } - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() == KeyEvent.VK_ENTER) { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); - if (node != null && node.isLeaf()) { - SketchReference sketch = (SketchReference) node.getUserObject(); - base.handleOpen(sketch.getPath()); - } - } - } - }); - - tree.addTreeExpansionListener(new TreeExpansionListener() { - @Override - public void treeExpanded(TreeExpansionEvent event) { - updateExpanded(tree); - } - - @Override - public void treeCollapsed(TreeExpansionEvent event) { - updateExpanded(tree); - } - }); - - tree.setBorder(new EmptyBorder(5, 5, 5, 5)); - if (Base.isMacOS()) { - tree.setToggleClickCount(2); - } else { - tree.setToggleClickCount(1); - } - } - protected void updateExpanded(JTree tree) { Enumeration en = tree.getExpandedDescendants(new TreePath(tree.getModel().getRoot())); //en.nextElement(); // skip the root "Examples" node diff --git a/app/src/processing/app/contrib/ExampleContribution.java b/app/src/processing/app/contrib/ExampleContribution.java index e9843c15d..e7d7575c4 100644 --- a/app/src/processing/app/contrib/ExampleContribution.java +++ b/app/src/processing/app/contrib/ExampleContribution.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.HashMap; import processing.app.Base; +import processing.core.PApplet; public class ExampleContribution extends LocalContribution { @@ -24,7 +25,7 @@ public class ExampleContribution extends LocalContribution { ArrayList modesList = new ArrayList(); if (unparsedModes == null || unparsedModes.isEmpty()) return modesList; - String[] splitStr = unparsedModes.split(","); + String[] splitStr = PApplet.trim(PApplet.split(unparsedModes, ','));//unparsedModes.split(","); for (String mode : splitStr) modesList.add(mode.trim()); return modesList; From 13889f84837bc96f2af25ec7070db328166c0607 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Thu, 7 Aug 2014 23:49:18 +0530 Subject: [PATCH 20/27] Rename to Examples-Package --- app/src/processing/app/Base.java | 16 +++++----- app/src/processing/app/Mode.java | 12 +++---- .../app/contrib/AvailableContribution.java | 4 +-- .../contrib/ContributionManagerDialog.java | 3 +- .../app/contrib/ContributionType.java | 32 +++++++++++-------- ....java => ExamplesPackageContribution.java} | 26 +++++++-------- 6 files changed, 49 insertions(+), 44 deletions(-) rename app/src/processing/app/contrib/{ExampleContribution.java => ExamplesPackageContribution.java} (70%) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index e1df82070..986b7467c 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -125,7 +125,7 @@ public class Base { //public List contribModes; protected ArrayList modeContribs; - protected ArrayList exampleContribs; + protected ArrayList exampleContribs; private JMenu sketchbookMenu; @@ -349,9 +349,9 @@ public class Base { */ void rebuildContribExamples() { if (exampleContribs == null) { - exampleContribs = new ArrayList(); + exampleContribs = new ArrayList(); } - ExampleContribution.loadMissing(this); + ExamplesPackageContribution.loadMissing(this); } @@ -404,7 +404,7 @@ public class Base { modeManagerFrame = new ContributionManagerDialog(ContributionType.MODE); exampleManagerFrame = - new ContributionManagerDialog(ContributionType.EXAMPLE); + new ContributionManagerDialog(ContributionType.EXAMPLES_PACKAGE); updateManagerFrame = new ContributionManagerDialog(null); @@ -678,7 +678,7 @@ public class Base { } - public ArrayList getExampleContribs() { + public ArrayList getExampleContribs() { return exampleContribs; } @@ -1956,7 +1956,7 @@ public class Base { getSketchbookLibrariesFolder().mkdir(); getSketchbookToolsFolder().mkdir(); getSketchbookModesFolder().mkdir(); - getSketchbookExamplesFolder().mkdir(); + getSketchbookExamplesPackagesFolder().mkdir(); // System.err.println("sketchbook: " + sketchbookFolder); } @@ -1988,8 +1988,8 @@ public class Base { } - static public File getSketchbookExamplesFolder() { - return new File(sketchbookFolder, "examples"); + static public File getSketchbookExamplesPackagesFolder() { + return new File(sketchbookFolder, "examples-packages"); } diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 426835ba5..8e27e17aa 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -35,7 +35,7 @@ import javax.swing.event.TreeExpansionListener; import javax.swing.tree.*; import processing.app.contrib.ContributionType; -import processing.app.contrib.ExampleContribution; +import processing.app.contrib.ExamplesPackageContribution; import processing.app.syntax.*; import processing.core.PApplet; @@ -106,7 +106,7 @@ public abstract class Mode { referenceFolder = new File(folder, "reference"); // Get path to the contributed examples compatible with this mode - examplesContribFolder = Base.getSketchbookExamplesFolder(); + examplesContribFolder = Base.getSketchbookExamplesPackagesFolder(); // rebuildToolbarMenu(); rebuildLibraryList(); @@ -675,15 +675,15 @@ public abstract class Mode { public DefaultMutableTreeNode buildContributedExamplesTrees() { - DefaultMutableTreeNode node = new DefaultMutableTreeNode("Contributed Examples"); + DefaultMutableTreeNode node = new DefaultMutableTreeNode("Contributed Examples-Packages"); try { - File[] subfolders = ContributionType.EXAMPLE.listCandidates(examplesContribFolder); + File[] subfolders = ContributionType.EXAMPLES_PACKAGE.listCandidates(examplesContribFolder); if (subfolders == null) { subfolders = new File[0]; //empty array } for (File sub : subfolders) { - if (!ExampleContribution.isExampleCompatible(base, sub)) + if (!ExamplesPackageContribution.isExamplesPackageCompatible(base, sub)) continue; DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); if (base.addSketches(subNode, sub)) { @@ -691,7 +691,7 @@ public abstract class Mode { System.out.println(subNode); int exampleNodeNumber = -1; for (int y = 0; y < subNode.getChildCount(); y++) - if (subNode.getChildAt(y).toString().equals("example")) + if (subNode.getChildAt(y).toString().equals("examples-package")) exampleNodeNumber = y; if (exampleNodeNumber == -1) continue; diff --git a/app/src/processing/app/contrib/AvailableContribution.java b/app/src/processing/app/contrib/AvailableContribution.java index e97643334..39b1cb1b0 100644 --- a/app/src/processing/app/contrib/AvailableContribution.java +++ b/app/src/processing/app/contrib/AvailableContribution.java @@ -271,7 +271,7 @@ class AvailableContribution extends Contribution { String compatibleContribsList = null; - if (getType() == ContributionType.EXAMPLE) { + if (getType() == ContributionType.EXAMPLES_PACKAGE) { compatibleContribsList = properties.get("compatibleModesList"); } @@ -300,7 +300,7 @@ class AvailableContribution extends Contribution { writer.println("version=" + version); writer.println("prettyVersion=" + prettyVersion); writer.println("lastUpdated=" + lastUpdated); - if (getType() == ContributionType.EXAMPLE) { + if (getType() == ContributionType.EXAMPLES_PACKAGE) { writer.println("compatibleModesList=" + compatibleContribsList); } diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 64cb5da93..641378b69 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -62,7 +62,6 @@ public class ContributionManagerDialog { if (type == null) { filter = ContributionType.createUpdateFilter(); } else { - filter = type.createFilter(); } contribListing = ContributionListing.getInstance(); @@ -395,7 +394,7 @@ public class ContributionManagerDialog { ArrayList modes = editor.getBase().getModeContribs(); contributions.addAll(modes); - ArrayList examples = editor.getBase().getExampleContribs(); + ArrayList examples = editor.getBase().getExampleContribs(); contributions.addAll(examples); // ArrayList compilations = LibraryCompilation.list(libraries); diff --git a/app/src/processing/app/contrib/ContributionType.java b/app/src/processing/app/contrib/ContributionType.java index 5e34b9d88..a2e661d98 100644 --- a/app/src/processing/app/contrib/ContributionType.java +++ b/app/src/processing/app/contrib/ContributionType.java @@ -31,7 +31,7 @@ import processing.app.Editor; import processing.app.Library; public enum ContributionType { - LIBRARY, TOOL, MODE, EXAMPLE; + LIBRARY, TOOL, MODE, EXAMPLES_PACKAGE; public String toString() { @@ -42,8 +42,8 @@ public enum ContributionType { return "tool"; case MODE: return "mode"; - case EXAMPLE: - return "example"; + case EXAMPLES_PACKAGE: + return "examples-package"; } return null; // should be unreachable }; @@ -55,7 +55,13 @@ public enum ContributionType { */ public String getTitle() { String s = toString(); - return Character.toUpperCase(s.charAt(0)) + s.substring(1); + if (this == EXAMPLES_PACKAGE) + return Character.toUpperCase(s.charAt(0)) + + s.substring(1, s.indexOf('-') + 1) + + Character.toUpperCase(s.charAt(s.indexOf('-') + 1)) + + s.substring(s.indexOf('-') + 2); + else + return Character.toUpperCase(s.charAt(0)) + s.substring(1); } @@ -67,8 +73,8 @@ public enum ContributionType { return "tools"; case MODE: return "modes"; - case EXAMPLE: - return "examples"; + case EXAMPLES_PACKAGE: + return "examples-package"; } return null; // should be unreachable } @@ -110,8 +116,8 @@ public enum ContributionType { if ("mode".equalsIgnoreCase(s)) { return MODE; } - if ("example".equalsIgnoreCase(s)) { - return EXAMPLE; + if ("examples-package".equalsIgnoreCase(s)) { + return EXAMPLES_PACKAGE; } } return null; @@ -126,8 +132,8 @@ public enum ContributionType { return Base.getSketchbookToolsFolder(); case MODE: return Base.getSketchbookModesFolder(); - case EXAMPLE: - return Base.getSketchbookExamplesFolder(); + case EXAMPLES_PACKAGE: + return Base.getSketchbookExamplesPackagesFolder(); } return null; } @@ -190,8 +196,8 @@ public enum ContributionType { return ToolContribution.load(folder); case MODE: return ModeContribution.load(base, folder); - case EXAMPLE: - return ExampleContribution.load(folder); + case EXAMPLES_PACKAGE: + return ExamplesPackageContribution.load(folder); } return null; } @@ -209,7 +215,7 @@ public enum ContributionType { case MODE: contribs.addAll(editor.getBase().getModeContribs()); break; - case EXAMPLE: + case EXAMPLES_PACKAGE: contribs.addAll(editor.getBase().getExampleContribs()); break; } diff --git a/app/src/processing/app/contrib/ExampleContribution.java b/app/src/processing/app/contrib/ExamplesPackageContribution.java similarity index 70% rename from app/src/processing/app/contrib/ExampleContribution.java rename to app/src/processing/app/contrib/ExamplesPackageContribution.java index e7d7575c4..f94cc6669 100644 --- a/app/src/processing/app/contrib/ExampleContribution.java +++ b/app/src/processing/app/contrib/ExamplesPackageContribution.java @@ -7,15 +7,15 @@ import java.util.HashMap; import processing.app.Base; import processing.core.PApplet; -public class ExampleContribution extends LocalContribution { +public class ExamplesPackageContribution extends LocalContribution { private ArrayList compatibleModesList; - static public ExampleContribution load(File folder) { - return new ExampleContribution(folder); + static public ExamplesPackageContribution load(File folder) { + return new ExamplesPackageContribution(folder); } - private ExampleContribution(File folder) { + private ExamplesPackageContribution(File folder) { super(folder); compatibleModesList = parseCompatibleModesList(properties .get("compatibleModesList")); @@ -40,10 +40,10 @@ public class ExampleContribution extends LocalContribution { * @return true if the example is compatible with the mode of the currently * active editor */ - public static boolean isExampleCompatible(Base base, + public static boolean isExamplesPackageCompatible(Base base, File exampleLocationFolder) { File propertiesFile = new File(exampleLocationFolder, - ContributionType.EXAMPLE.toString() + ContributionType.EXAMPLES_PACKAGE.toString() + ".properties"); if (propertiesFile.exists()) { ArrayList compModesList = parseCompatibleModesList(Base @@ -58,20 +58,20 @@ public class ExampleContribution extends LocalContribution { } static public void loadMissing(Base base) { - File examplesFolder = Base.getSketchbookExamplesFolder(); - ArrayList contribExamples = base.getExampleContribs(); + File examplesFolder = Base.getSketchbookExamplesPackagesFolder(); + ArrayList contribExamples = base.getExampleContribs(); - HashMap existing = new HashMap(); - for (ExampleContribution contrib : contribExamples) { + HashMap existing = new HashMap(); + for (ExamplesPackageContribution contrib : contribExamples) { existing.put(contrib.getFolder(), contrib); } - File[] potential = ContributionType.EXAMPLE.listCandidates(examplesFolder); + File[] potential = ContributionType.EXAMPLES_PACKAGE.listCandidates(examplesFolder); // If modesFolder does not exist or is inaccessible (folks might like to // mess with folders then report it as a bug) 'potential' will be null. if (potential != null) { for (File folder : potential) { if (!existing.containsKey(folder)) { - contribExamples.add(new ExampleContribution(folder)); + contribExamples.add(new ExamplesPackageContribution(folder)); } } } @@ -79,7 +79,7 @@ public class ExampleContribution extends LocalContribution { @Override public ContributionType getType() { - return ContributionType.EXAMPLE; + return ContributionType.EXAMPLES_PACKAGE; } public ArrayList getCompatibleModesList() { From c67b0c8495e29f6d24ebda361c44505652a88e49 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sat, 9 Aug 2014 14:11:38 +0530 Subject: [PATCH 21/27] Redesigning 'Add Examples...' button --- app/src/processing/app/Mode.java | 33 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 8e27e17aa..621692bb8 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -29,6 +29,7 @@ import java.io.*; import java.util.*; import javax.swing.*; +import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; @@ -739,16 +740,22 @@ public abstract class Mode { }); JPanel examplesPanel = new JPanel(); - examplesPanel.setLayout(new BoxLayout(examplesPanel, BoxLayout.PAGE_AXIS)); + examplesPanel.setLayout(new BorderLayout()); examplesPanel.setBackground(Color.WHITE); - final JLabel openExamplesManagerLabel = new JLabel("Add Example..."); - openExamplesManagerLabel.setOpaque(false); - openExamplesManagerLabel.setBorder(new EmptyBorder(10, 6, 1, 5)); - openExamplesManagerLabel.setAlignmentX(Component.LEFT_ALIGNMENT); - openExamplesManagerLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - openExamplesManagerLabel.setForeground(new Color(0, 0, 238)); - openExamplesManagerLabel.addMouseListener(new MouseListener() { + final JPanel openExamplesManagerPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + JLabel openExamplesManagerLabel = new JLabel("Add Examples..."); +// openExamplesManagerLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + openExamplesManagerPanel.add(openExamplesManagerLabel); + openExamplesManagerPanel.setOpaque(false); + Border lineBorder = BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK); + Border paddingBorder = BorderFactory.createEmptyBorder(3, 5, 1, 4); + openExamplesManagerPanel.setBorder(BorderFactory.createCompoundBorder(lineBorder, paddingBorder)); +// openExamplesManagerLabel.set + openExamplesManagerPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + openExamplesManagerPanel.setCursor(new Cursor(Cursor.HAND_CURSOR)); +// openExamplesManagerLabel.setForeground(new Color(0, 0, 238)); + openExamplesManagerPanel.addMouseListener(new MouseListener() { @Override public void mouseReleased(MouseEvent e) {} @@ -765,7 +772,7 @@ public abstract class Mode { @Override public void mouseClicked(MouseEvent e) { base.handleOpenExampleManager(); - openExamplesManagerLabel.setForeground(new Color(85, 26, 139)); +// openExamplesManagerLabel.setForeground(new Color(85, 26, 139)); } }); @@ -835,7 +842,7 @@ public abstract class Mode { } }); - tree.setBorder(new EmptyBorder(5, 5, 5, 5)); + tree.setBorder(new EmptyBorder(0, 5, 5, 5)); if (Base.isMacOS()) { tree.setToggleClickCount(2); } else { @@ -844,13 +851,13 @@ public abstract class Mode { JScrollPane treePane = new JScrollPane(tree); treePane.setPreferredSize(new Dimension(250, 300)); - treePane.setBorder(new EmptyBorder(5, 0, 0, 0)); + treePane.setBorder(new EmptyBorder(2, 0, 0, 0)); treePane.setOpaque(true); treePane.setBackground(Color.WHITE); treePane.setAlignmentX(Component.LEFT_ALIGNMENT); - examplesPanel.add(openExamplesManagerLabel); - examplesPanel.add(treePane); + examplesPanel.add(openExamplesManagerPanel,BorderLayout.PAGE_START); + examplesPanel.add(treePane, BorderLayout.CENTER); examplesFrame.getContentPane().add(examplesPanel); examplesFrame.pack(); From 2386d9673367e03d896197fe46cd2b8b87902c9c Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sat, 9 Aug 2014 23:54:23 +0530 Subject: [PATCH 22/27] Added 'Add Examples...' option to Open Toolbar Menu --- app/src/processing/app/Mode.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index 621692bb8..fdf7170d1 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -412,6 +412,14 @@ public abstract class Mode { } }); toolbarMenu.add(item); + + item = new JMenuItem("Add Examples..."); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + base.handleOpenExampleManager(); + } + }); + toolbarMenu.add(item); // Add a list of all sketches and subfolders toolbarMenu.addSeparator(); From 9faa8eac9afbacd31504f26227886548b3505a87 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sun, 10 Aug 2014 01:13:29 +0530 Subject: [PATCH 23/27] Solve old folders displaying --- app/src/processing/app/Base.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 986b7467c..1ae9bccfb 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -1508,7 +1508,7 @@ public class Base { JMenu submenu = new JMenu(name); // needs to be separate var otherwise would set ifound to false boolean anything = addSketches(submenu, subfolder, replaceExisting); - if (anything) { + if (anything && !name.equals("old")) { //Don't add old contributions menu.add(submenu); found = true; } From b8fddbaaeab7a6d7bb833ce8983529c29b94124e Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sun, 10 Aug 2014 22:07:01 +0530 Subject: [PATCH 24/27] Added function to colourize alternate rows of a JTree Thus improving the Examples Tree UI appearance --- app/src/processing/app/Mode.java | 98 +++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/app/src/processing/app/Mode.java b/app/src/processing/app/Mode.java index fdf7170d1..b51e50438 100644 --- a/app/src/processing/app/Mode.java +++ b/app/src/processing/app/Mode.java @@ -33,6 +33,7 @@ import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; +import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.*; import processing.app.contrib.ContributionType; @@ -684,7 +685,7 @@ public abstract class Mode { public DefaultMutableTreeNode buildContributedExamplesTrees() { - DefaultMutableTreeNode node = new DefaultMutableTreeNode("Contributed Examples-Packages"); + DefaultMutableTreeNode node = new DefaultMutableTreeNode("Contributed Examples"); try { File[] subfolders = ContributionType.EXAMPLES_PACKAGE.listCandidates(examplesContribFolder); @@ -697,7 +698,6 @@ public abstract class Mode { DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(sub.getName()); if (base.addSketches(subNode, sub)) { node.add(subNode); - System.out.println(subNode); int exampleNodeNumber = -1; for (int y = 0; y < subNode.getChildCount(); y++) if (subNode.getChildAt(y).toString().equals("examples-package")) @@ -709,7 +709,6 @@ public abstract class Mode { int count = exampleNode.getChildCount(); for (int x = 0; x < count; x++) { subNode.add((DefaultMutableTreeNode) exampleNode.getChildAt(0)); - System.out.println(subNode); } } } @@ -737,6 +736,98 @@ public abstract class Mode { } + /** + * Function to give a JTree a pretty alternating gray-white colouring for + * its rows. + * + * @param tree + */ + private void colourizeTreeRows(JTree tree) { + // Code in this function adapted from: + // http://mateuszstankiewicz.eu/?p=263 + tree.setCellRenderer(new DefaultTreeCellRenderer() { + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + JComponent c = (JComponent) super + .getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, + hasFocus); + + if (!tree.isRowSelected(row)) { + if (row % 2 == 0) { + + // Need to set this, else the gray from the odd + // rows colours this gray as well. + c.setBackground(new Color(255, 255, 255)); + + setBackgroundSelectionColor(new Color(0, 0, 255)); + setTextSelectionColor(Color.WHITE); + setBorderSelectionColor(new Color(0, 0, 255)); + } else { + + // Set background for entire component (including the image). + // Using transparency messes things up, probably since the + // transparent colour is not good friends with the images background colour. + c.setBackground(new Color(240, 240, 240)); + + // Can't use setBackgroundSelectionColor() directly, since then, the + // image's background isn't affected. + // The setUI() doesn't fix the image's background because the + // transparency likely interferes with its normal background, + // making its background lighter than the rest. +// setBackgroundNonSelectionColor(new Color(190, 190, 190)); + + setBackgroundSelectionColor(new Color(0, 0, 255)); + setTextSelectionColor(Color.WHITE); + setBorderSelectionColor(new Color(0, 0, 255)); + } + } else {// Transparent blue if selected + c.setBackground(new Color(127, 127, 255)); + } + + c.setOpaque(true); + return c; + } + + }); + + tree.setUI(new BasicTreeUI() { + + @Override + protected void paintRow(Graphics g, Rectangle clipBounds, Insets insets, + Rectangle bounds, TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) { + Graphics g2 = g.create(); + + if (!tree.isRowSelected(row)) { + if (row % 2 == 0) { + // Need to set this, else the gray from the odd rows + // affects the even rows too. + g2.setColor(new Color(255, 255, 255, 128)); + } else { + // Transparent light-gray + g2.setColor(new Color(226, 226, 226, 128)); + } + } else + // Transparent blue if selected + g2.setColor(new Color(0, 0, 255, 128)); + + g2.fillRect(0, bounds.y, tree.getWidth(), bounds.height); + + g2.dispose(); + + super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, + hasBeenExpanded, isLeaf); + } + }); + } + + public void showExamplesFrame() { if (examplesFrame == null) { examplesFrame = new JFrame(getTitle() + " " + Language.text("examples")); @@ -786,6 +877,7 @@ public abstract class Mode { final JTree tree = new JTree(buildExamplesTree()); + colourizeTreeRows(tree); tree.setOpaque(true); tree.setAlignmentX(Component.LEFT_ALIGNMENT); From c4c146288259f9e15880bdfb3514c70a6f7a03cf Mon Sep 17 00:00:00 2001 From: Joel Moniz Date: Fri, 15 Aug 2014 22:15:23 +0530 Subject: [PATCH 25/27] Made errors a little more helpful Also, Hide stack traces when error message provided --- .../app/contrib/ContributionManager.java | 22 ++++++++++++++++--- .../contrib/ContributionManagerDialog.java | 1 - .../processing/app/languages/PDE.properties | 6 +++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/app/src/processing/app/contrib/ContributionManager.java b/app/src/processing/app/contrib/ContributionManager.java index 034246be7..b64c42556 100644 --- a/app/src/processing/app/contrib/ContributionManager.java +++ b/app/src/processing/app/contrib/ContributionManager.java @@ -102,7 +102,8 @@ public class ContributionManager { } catch (IOException ioe) { if (progress != null) progress.error(ioe); - ioe.printStackTrace(); + // Hiding stack trace. An error has been shown where needed. +// ioe.printStackTrace(); } if (progress != null) progress.finished(); @@ -155,11 +156,26 @@ public class ContributionManager { } installProgress.finished(); } + else { + if (downloadProgress.exception instanceof SocketTimeoutException) { + status.setErrorMessage(Language + .interpolate("contrib.errors.contrib_download.timeout", + ad.getName())); + } else { + status.setErrorMessage(Language + .interpolate("contrib.errors.download_and_install", + ad.getName())); + } + } contribZip.delete(); } catch (Exception e) { - e.printStackTrace(); - status.setErrorMessage(Language.text("contrib.errors.download_and_install")); + // Hiding stack trace. The error message ought to suffice. +// e.printStackTrace(); + status + .setErrorMessage(Language + .interpolate("contrib.errors.download_and_install", + ad.getName())); } } catch (IOException e) { status.setErrorMessage(Language.text("contrib.errors.temporary_directory")); diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 82d4d79ad..6065b75dd 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -411,7 +411,6 @@ public class ContributionManagerDialog { } } - protected void setFilterText(String filter) { if (filter == null || filter.isEmpty()) { filterField.setText(""); diff --git a/app/src/processing/app/languages/PDE.properties b/app/src/processing/app/languages/PDE.properties index fa80b739d..aaa592413 100644 --- a/app/src/processing/app/languages/PDE.properties +++ b/app/src/processing/app/languages/PDE.properties @@ -269,15 +269,17 @@ contrib.messages.install_restart = Please restart Processing to finish installin contrib.messages.update_restart = Please restart Processing to finish updating this item. contrib.errors.list_download = Could not download the list of available contributions. contrib.errors.list_download.timeout = Connection timed out while downloading the contribution list. -contrib.errors.download_and_install = Error during download and install. +contrib.errors.download_and_install = Error during download and install of %s. contrib.errors.description_unavailable = Description unavailable. -contrib.errors.malformed_url = "The link fetched from Processing.org is not valid.\nYou can still install this library manually by visiting\nthe library's website. +contrib.errors.malformed_url = The link fetched from Processing.org is not valid.\nYou can still install this library manually by visiting\nthe library's website. contrib.errors.needs_repackage = %s needs to be repackaged according to the %s guidelines. contrib.errors.no_contribution_found = Could not find a %s in the downloaded file. contrib.errors.overwriting_properties = Error overwriting .properties file. contrib.errors.install_failed = Install failed. contrib.errors.update_on_restart_failed = Update on restart of %s failed. contrib.errors.temporary_directory = Could not write to temporary directory. +contrib.errors.contrib_download.timeout = Connection timed out while downloading %s. +contrib.errors.no_internet_connection = You don't seem to be connected to the Internet. contrib.all = All contrib.undo = Undo contrib.remove = Remove From d13038091b4e80d11a2c8476c1b759c6f19ac13b Mon Sep 17 00:00:00 2001 From: Joel Moniz Date: Sat, 16 Aug 2014 00:36:23 +0530 Subject: [PATCH 26/27] Disabled Install & Update buttons if Internet isn't available --- app/src/processing/app/contrib/ContributionListing.java | 8 ++++++++ app/src/processing/app/contrib/ContributionPanel.java | 2 ++ 2 files changed, 10 insertions(+) diff --git a/app/src/processing/app/contrib/ContributionListing.java b/app/src/processing/app/contrib/ContributionListing.java index 083f85685..2044303f1 100644 --- a/app/src/processing/app/contrib/ContributionListing.java +++ b/app/src/processing/app/contrib/ContributionListing.java @@ -44,6 +44,7 @@ public class ContributionListing { Map> librariesByCategory; ArrayList allContributions; boolean hasDownloadedLatestList; + boolean hasListDownloadFailed; ReentrantLock downloadingListingLock; @@ -371,6 +372,8 @@ public class ContributionListing { hasDownloadedLatestList = true; setAdvertisedList(listingFile); } + else + hasListDownloadFailed = true; } downloadingListingLock.unlock(); } @@ -436,6 +439,11 @@ public class ContributionListing { } + boolean hasListDownloadFailed() { + return hasListDownloadFailed; + } + + // /** // * @return a lowercase string with all non-alphabetic characters removed // */ diff --git a/app/src/processing/app/contrib/ContributionPanel.java b/app/src/processing/app/contrib/ContributionPanel.java index 68434f2bc..66781601d 100644 --- a/app/src/processing/app/contrib/ContributionPanel.java +++ b/app/src/processing/app/contrib/ContributionPanel.java @@ -761,8 +761,10 @@ class ContributionPanel extends JPanel { if (contrib != null) { updateButton.setVisible((contribListing.hasUpdates(contrib) && !contrib.isUpdateFlagged() && !contrib.isDeletionFlagged()) || isUpdateInProgress); + updateButton.setEnabled(!contribListing.hasListDownloadFailed()); } installRemoveButton.setVisible(isSelected() || installRemoveButton.getText().equals(Language.text("contrib.remove")) || isUpdateInProgress); + installRemoveButton.setEnabled(installRemoveButton.getText().equals(Language.text("contrib.remove")) ||!contribListing.hasListDownloadFailed()); reorganizePaneComponents(); // for (JTextPane textPane : headerPaneSet) { From 35ad4d4a216c9b3c255b5a3243dfe1716480a242 Mon Sep 17 00:00:00 2001 From: Joel Moniz Date: Sat, 16 Aug 2014 01:10:32 +0530 Subject: [PATCH 27/27] Added a retry button to try to download contribs.txt again --- .../app/contrib/ContributionListing.java | 1 + .../contrib/ContributionManagerDialog.java | 65 ++++++++++++++----- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/app/src/processing/app/contrib/ContributionListing.java b/app/src/processing/app/contrib/ContributionListing.java index 2044303f1..e2f172075 100644 --- a/app/src/processing/app/contrib/ContributionListing.java +++ b/app/src/processing/app/contrib/ContributionListing.java @@ -370,6 +370,7 @@ public class ContributionListing { ContributionManager.download(url, listingFile, progress); if (!progress.isCanceled() && !progress.isError()) { hasDownloadedLatestList = true; + hasListDownloadFailed = false; setAdvertisedList(listingFile); } else diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 6065b75dd..32dedb0ed 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -51,6 +51,7 @@ public class ContributionManagerDialog { StatusPanel status; FilterField filterField; JButton restartButton; + JButton retryConnectingButton; // the calling editor, so updates can be applied Editor editor; @@ -132,6 +133,16 @@ public class ContributionManagerDialog { }); + retryConnectingButton = new JButton("Retry"); + retryConnectingButton.setVisible(false); + retryConnectingButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + downloadAndUpdateContributionListing(); + } + }); + Toolkit.setIcon(dialog); createComponents(); registerDisposeListeners(); @@ -146,23 +157,7 @@ public class ContributionManagerDialog { updateContributionListing(); } else { - contribListing.downloadAvailableList(new ProgressMonitor() { - - public void finished() { - super.finished(); - - updateContributionListing(); - updateCategoryChooser(); - if (error) { - if (exception instanceof SocketTimeoutException) { - status.setErrorMessage(Language.text("contrib.errors.list_download.timeout")); - } else { - status.setErrorMessage(Language.text("contrib.errors.list_download")); - } - exception.printStackTrace(); - } - } - }); + downloadAndUpdateContributionListing(); } } @@ -259,7 +254,11 @@ public class ContributionManagerDialog { statusRestartPane.setOpaque(false); statusRestartPane.add(status, BorderLayout.WEST); + + // Adding both of these to EAST shouldn't pose too much of a problem, + // since they can never get added together. statusRestartPane.add(restartButton, BorderLayout.EAST); + statusRestartPane.add(retryConnectingButton, BorderLayout.EAST); pane.add(statusRestartPane, BorderLayout.SOUTH); @@ -411,6 +410,38 @@ public class ContributionManagerDialog { } } + + protected void downloadAndUpdateContributionListing() { + status.setMessage("Downloading contribution list..."); + retryConnectingButton.setEnabled(false); + contribListing.downloadAvailableList(new ProgressMonitor() { + + public void finished() { + super.finished(); + + updateContributionListing(); + updateCategoryChooser(); + + retryConnectingButton.setEnabled(true); + + if (error) { + if (exception instanceof SocketTimeoutException) { + status.setErrorMessage(Language.text("contrib.errors.list_download.timeout")); + } else { + status.setErrorMessage(Language.text("contrib.errors.list_download")); + } + exception.printStackTrace(); + retryConnectingButton.setVisible(true); + } + else { + status.setMessage("Done."); + retryConnectingButton.setVisible(false); + } + } + }); + } + + protected void setFilterText(String filter) { if (filter == null || filter.isEmpty()) { filterField.setText("");