Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/resources/languages/PDE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,9 @@ sketchbook = Sketchbook
sketchbook.tree = Sketchbook

# Examples (Frame)
examples.frame = Examples
examples.title = %s Examples
examples.description = Browse the examples included with Processing, as well as contributed examples from libraries you have installed.
examples.add_examples = Add Examples...
examples.libraries = Contributed Libraries
examples.core_libraries = Libraries
Expand Down
36 changes: 16 additions & 20 deletions app/src/processing/app/Mode.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,21 @@

package processing.app;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.List;

import javax.swing.*;

import processing.app.contrib.ContributionManager;
import processing.app.syntax.*;
import processing.app.ui.Editor;
import processing.app.ui.EditorException;
import processing.app.ui.EditorState;
import processing.app.ui.ExamplesFrame;
import processing.app.ui.Recent;
import processing.app.syntax.PdeTokenMarker;
import processing.app.syntax.TokenMarker;
import processing.app.ui.*;
import processing.app.ui.Toolkit;
import processing.core.PApplet;
import processing.utils.SketchException;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.*;
import java.util.List;


public abstract class Mode {
protected Base base;
Expand Down Expand Up @@ -87,9 +83,12 @@ public abstract class Mode {
*/
protected ClassLoader classLoader;

public Mode(Base base, File folder) {
this(folder);
this.base = base;
}

public Mode(Base base, File folder) {
this.base = base;
public Mode(File folder) {
this.folder = folder;
tokenMarker = createTokenMarker();

Expand Down Expand Up @@ -605,10 +604,7 @@ public void rebuildExamplesFrame() {


public void showExamplesFrame() {
if (examplesFrame == null) {
examplesFrame = new ExamplesFrame(base, this);
}
examplesFrame.setVisible();
PDEExamplesKt.show(this, base);
}


Expand Down
15 changes: 5 additions & 10 deletions app/src/processing/app/Sketch.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@
import processing.app.ui.Editor;
import processing.app.ui.Recent;
import processing.app.ui.Toolkit;
import processing.core.*;
import processing.core.PApplet;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FileDialog;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
Expand All @@ -42,9 +40,6 @@
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.*;
import javax.swing.border.EmptyBorder;


/**
* Stores information about files in the current sketch.
Expand Down Expand Up @@ -1314,7 +1309,7 @@ static protected Settings loadProperties(File folder) throws IOException {
* Because the default mode will be the first in the list, this will always
* prefer that one over the others.
*/
static protected File findMain(File folder, List<Mode> modeList) {
static public File findMain(File folder, List<Mode> modeList) {
try {
Settings props = Sketch.loadProperties(folder);
String main = props.get("main");
Expand Down
171 changes: 171 additions & 0 deletions app/src/processing/app/api/Mode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package processing.app.api

import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.toMutableStateList
import kotlinx.coroutines.*
import processing.app.Mode
import processing.app.contrib.ContributionType
import java.io.File
import java.nio.file.*
import kotlin.io.path.isDirectory
import kotlin.io.path.name

class Mode {
companion object {
/**
* Find sketches in the given root folder for the specified mode.
*
* Based on ExamplesFrame.buildTree()
*
* @param root The root directory to search for sketches.
* @param mode The mode to filter sketches by.
* @return A list of sketch folders found in the root directory.
*/
fun findExampleSketches(
mode: Mode,
sketchbookFolder: File? = null,
scope: CoroutineScope? = null
): List<Sketch.Companion.Folder> {
val baseExamples = mode.exampleCategoryFolders.mapNotNull {
searchForSketches(it.toPath(), mode, { true }, scope)
}

val coreLibraryExamples = mode.coreLibraries.mapNotNull {
searchForSketches(it.examplesFolder.toPath(), mode, { true }, scope).replace(
name = it.name,
path = it.path
)
}.wrap(
name = "Libraries",
path = File(mode.coreLibraries.first().path).parent.toString()
)

val contributedLibraryExamples = mode.contribLibraries.mapNotNull {
searchForSketches(it.examplesFolder.toPath(), mode, { true }, scope).replace(
name = it.name,
path = it.path
)
}.wrap(
name = "Contributed Libraries",
path = File(mode.contribLibraries.firstOrNull()?.path ?: mode.getContentFile("").path).parent.toString()
)

val contributedExamplePacks = sketchbookFolder?.let { root ->
ContributionType.EXAMPLES.listCandidates(root).mapNotNull {
searchForSketches(it.toPath(), mode, { true }, scope)
}
}
return (baseExamples + coreLibraryExamples + contributedLibraryExamples + (contributedExamplePacks
?: emptyList()))
}

/**
* Find sketches in the given root folder for the specified mode.
*
* Based on Base.addSketches()
*
* @param root The root directory to search for sketches.
* @param mode The mode to filter sketches by.
* @return A list of sketch folders found in the root directory.
*/
fun searchForSketches(
root: Path,
mode: Mode,
filter: ((Path) -> Boolean) = { true },
scope: CoroutineScope? = null
): Sketch.Companion.Folder? {
if (!root.isDirectory()) return null
if (!filter(root)) return null

val stream = Files.newDirectoryStream(root)
val (sketchFolders, subfolders) = stream
.filter { path -> path.isDirectory() }
.filter { path -> filter(path) }
.partition { path ->
val main = processing.app.Sketch.findMain(path.toFile(), listOf(mode))
main != null
}
val sketches = sketchFolders.map {
Sketch.Companion.Sketch(
name = it.fileName.toString(),
path = it.toString(),
mode = mode.identifier
)
}.toMutableStateList()
val children = subfolders.mapNotNull {
searchForSketches(it, mode, filter)
}.toMutableStateList()
if (sketches.isEmpty() && children.isEmpty()) return null

scope?.launch(Dispatchers.IO) {
val watchService: WatchService = FileSystems
.getDefault()
.newWatchService()

val watcher = root.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY)
while (isActive) {
delay(100)
watchService.poll() ?: continue

watcher.pollEvents().forEach { _ ->
val updatedFolder = searchForSketches(root, mode, filter) ?: return@forEach

sketches.clear()
sketches.addAll(updatedFolder.sketches)
children.clear()
children.addAll(updatedFolder.children)
}

}
}

return Sketch.Companion.Folder(
name = root.name,
path = root.toString(),
sketches = sketches,
children = children
)
}

fun Sketch.Companion.Folder?.wrap(
name: String? = this?.name,
path: String? = this?.path
): Sketch.Companion.Folder? {
if (this == null) return null;
return Sketch.Companion.Folder(
name = name ?: this.name,
path = path ?: this.path,
sketches = mutableStateListOf(),
children = mutableStateListOf(this)
)
}

fun List<Sketch.Companion.Folder>.wrap(
name: String,
path: String,
): List<Sketch.Companion.Folder> {
if (this.isEmpty()) return emptyList()
return listOf(
Sketch.Companion.Folder(
name = name,
path = path,
sketches = mutableStateListOf(),
children = this.toMutableStateList()
)
)
}

fun Sketch.Companion.Folder?.replace(
name: String? = this?.name,
path: String? = this?.path
): Sketch.Companion.Folder? {
if (this == null) return null;
return Sketch.Companion.Folder(
name = name ?: this.name,
path = path ?: this.path,
sketches = this.sketches,
children = this.children
)
}
}
}
51 changes: 15 additions & 36 deletions app/src/processing/app/ui/ExamplesFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,20 @@

package processing.app.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import processing.app.*;
import processing.app.contrib.Contribution;
import processing.app.contrib.ContributionManager;
import processing.app.contrib.ContributionType;
import processing.app.contrib.ExamplesContribution;
import processing.core.PApplet;
import processing.data.StringDict;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
Expand All @@ -37,36 +46,6 @@
import java.util.Comparator;
import java.util.Enumeration;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import processing.app.Base;
import processing.app.Language;
import processing.app.Library;
import processing.app.Mode;
import processing.app.Platform;
import processing.app.Preferences;
import processing.app.SketchReference;
import processing.app.contrib.Contribution;
import processing.app.contrib.ContributionManager;
import processing.app.contrib.ContributionType;
import processing.app.contrib.ExamplesContribution;

import processing.core.PApplet;
import processing.data.StringDict;


public class ExamplesFrame extends JFrame {
protected Base base;
Expand Down Expand Up @@ -283,7 +262,7 @@ void expandTree(JTree tree, Object object, String[] items,
}
}


@Deprecated
protected DefaultMutableTreeNode buildTree() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(); //"Examples");

Expand Down
Loading