projekti pod git sistemom za održavanje verzija -- projects under
the git version control system
1 import java
.util
.ArrayList
;
2 import java
.util
.HashMap
;
3 import java
.util
.LinkedHashMap
;
6 import java
.util
.function
.Function
;
8 import javafx
.application
.Application
;
9 import javafx
.application
.Platform
;
10 import javafx
.collections
.FXCollections
;
11 import javafx
.collections
.ObservableList
;
12 import javafx
.geometry
.Insets
;
13 import javafx
.geometry
.VPos
;
14 import javafx
.embed
.swing
.JFXPanel
;
15 import javafx
.scene
.Scene
;
16 import javafx
.scene
.canvas
.Canvas
;
17 import javafx
.scene
.canvas
.GraphicsContext
;
18 import javafx
.scene
.control
.Button
;
19 import javafx
.scene
.control
.Label
;
20 import javafx
.scene
.control
.ListCell
;
21 import javafx
.scene
.control
.ListView
;
22 import javafx
.scene
.control
.Slider
;
23 import javafx
.scene
.layout
.BorderPane
;
24 import javafx
.scene
.layout
.ColumnConstraints
;
25 import javafx
.scene
.layout
.GridPane
;
26 import javafx
.scene
.layout
.Priority
;
27 import javafx
.scene
.layout
.StackPane
;
28 import javafx
.scene
.layout
.VBox
;
29 import javafx
.scene
.paint
.Color
;
30 import javafx
.scene
.paint
.Paint
;
31 import javafx
.scene
.shape
.Circle
;
32 import javafx
.scene
.shape
.StrokeLineCap
;
33 import javafx
.scene
.shape
.StrokeLineJoin
;
34 import javafx
.scene
.text
.Font
;
35 import javafx
.scene
.text
.FontWeight
;
36 import javafx
.scene
.text
.TextAlignment
;
37 import javafx
.stage
.Stage
;
39 public class Prikaz
extends Application
{
41 public static final Color STVARNO_BELA
= Color
.hsb(0, 0, 1.0);
42 public static final Color BELA
= Color
.hsb(0, 0, 0.95);
43 public static final Color SVETLO_SIVA
= Color
.hsb(0, 0, 0.8);
44 public static final Color SIVA
= Color
.hsb(0, 0, 0.6);
45 public static final Color TAMNO_SIVA
= Color
.hsb(0, 0, 0.4);
46 public static final Color CRNA
= Color
.hsb(0, 0, 0.2);
47 public static final Color STVARNO_CRNA
= Color
.hsb(0, 0, 0.0);
49 public static final Color SVETLO_CRVENA
= Color
.hsb( 0, 0.2, 1.0);
50 public static final Color SVETLO_NARANDZASTA
= Color
.hsb( 30, 0.2, 1.0);
51 public static final Color SVETLO_ZUTA
= Color
.hsb( 60, 0.2, 1.0);
52 public static final Color SVETLO_ZELENA
= Color
.hsb(120, 0.2, 1.0);
53 public static final Color SVETLO_TIRKIZNA
= Color
.hsb(180, 0.2, 1.0);
54 public static final Color SVETLO_AZURNA
= Color
.hsb(210, 0.2, 1.0);
55 public static final Color SVETLO_PLAVA
= Color
.hsb(240, 0.2, 1.0);
56 public static final Color SVETLO_PURPURNA
= Color
.hsb(270, 0.2, 1.0);
57 public static final Color SVETLO_LJUBICASTA
= Color
.hsb(300, 0.2, 1.0);
58 public static final Color SVETLO_RUZICASTA
= Color
.hsb(330, 0.2, 1.0);
60 public static final Color CRVENA
= Color
.hsb( 0, 0.9, 0.8);
61 public static final Color NARANDZASTA
= Color
.hsb( 30, 0.9, 0.8);
62 public static final Color ZUTA
= Color
.hsb( 60, 0.9, 0.8);
63 public static final Color ZELENA
= Color
.hsb(120, 0.9, 0.8);
64 public static final Color TIRKIZNA
= Color
.hsb(180, 0.9, 0.8);
65 public static final Color AZURNA
= Color
.hsb(210, 0.9, 0.8);
66 public static final Color PLAVA
= Color
.hsb(240, 0.9, 0.8);
67 public static final Color PURPURNA
= Color
.hsb(270, 0.9, 0.8);
68 public static final Color LJUBICASTA
= Color
.hsb(300, 0.9, 0.8);
69 public static final Color RUZICASTA
= Color
.hsb(330, 0.9, 0.8);
71 public static final Color TAMNO_CRVENA
= Color
.hsb( 0, 0.8, 0.4);
72 public static final Color TAMNO_NARANDZASTA
= Color
.hsb( 30, 0.8, 0.4);
73 public static final Color TAMNO_ZUTA
= Color
.hsb( 60, 0.8, 0.4);
74 public static final Color TAMNO_ZELENA
= Color
.hsb(120, 0.8, 0.4);
75 public static final Color TAMNO_TIRKIZNA
= Color
.hsb(180, 0.8, 0.4);
76 public static final Color TAMNO_AZURNA
= Color
.hsb(210, 0.8, 0.4);
77 public static final Color TAMNO_PLAVA
= Color
.hsb(240, 0.8, 0.4);
78 public static final Color TAMNO_PURPURNA
= Color
.hsb(270, 0.8, 0.4);
79 public static final Color TAMNO_LJUBICASTA
= Color
.hsb(300, 0.8, 0.4);
80 public static final Color TAMNO_RUZICASTA
= Color
.hsb(330, 0.8, 0.4);
86 protected static Paint bojaPozadine
= BELA
;
87 protected static Paint bojaOkvira
= CRNA
;
88 protected static Map
<Integer
, Paint
> bojaPoljaPozadina
= new HashMap
<>();
89 protected static Map
<Integer
, Paint
> bojaPoljaTekst
= new HashMap
<>();
90 protected static Font font
= Font
.font("Arial", FontWeight
.BOLD
, 12);
92 public static void boja(Paint pozadina
, Paint okvir
) {
93 bojaPozadine
= pozadina
;
97 public static void boja(int vrednost
, Paint bojaPozadine
, Paint bojaTeksta
) {
98 if (bojaPozadine
== null) {
99 bojaPoljaPozadina
.remove(vrednost
);
101 bojaPoljaPozadina
.put(vrednost
, bojaPozadine
);
102 if (bojaTeksta
== null) {
103 bojaPoljaTekst
.remove(vrednost
);
105 bojaPoljaTekst
.put(vrednost
, bojaTeksta
);
108 public static void boja(int vrednostMin
, int vrednostMax
, Color bojaMin
, Color bojaMax
, Paint bojaTeksta
) {
109 if (bojaMin
== null || bojaMax
== null) {
110 throw new IllegalArgumentException();
112 int n
= vrednostMax
- vrednostMin
;
113 for (int i
= 0; i
<= n
; i
++) {
114 int vrednost
= vrednostMin
+ i
;
115 bojaPoljaPozadina
.put(vrednost
, bojaMin
.interpolate(bojaMax
, (double) (i
) / n
));
116 if (bojaTeksta
== null) {
117 bojaPoljaTekst
.remove(vrednost
);
119 bojaPoljaTekst
.put(vrednost
, bojaTeksta
);
127 private static double velicinaPolja
= 32;
128 private static double velicinaRazmaka
= 4;
129 private static int debljinaOkvira
= 0;
130 private static double debljinaPuta
= velicinaPolja
/ 2;
132 public static void velicina(double polje
, double razmak
, int okvir
) {
133 velicinaPolja
= polje
;
134 velicinaRazmaka
= razmak
;
135 debljinaOkvira
= okvir
;
136 debljinaPuta
= velicinaPolja
/ 2;
139 protected static double ukupnaDuzina(int brojPolja
) {
140 return x(brojPolja
+ debljinaOkvira
, 0.0);
143 protected static double x(int indeks
, double delta
) {
144 indeks
= indeks
+ debljinaOkvira
;
145 return indeks
* (velicinaPolja
+ velicinaRazmaka
) + velicinaRazmaka
+ velicinaPolja
* delta
;
148 protected static double x(int indeks
) {
149 return x(indeks
, 0.0);
152 protected static double k(int indeks
) {
153 return x(indeks
, 0.5);
156 protected static double w(int count
, double delta
) {
157 return (velicinaPolja
+ velicinaRazmaka
) * count
+ velicinaRazmaka
* (delta
- 1);
160 protected static double w(int count
) {
164 protected static double r() {
165 return 2 * velicinaRazmaka
;
172 protected static String naslovProzora
;
173 protected static int sirinaMape
;
174 protected static int visinaMape
;
175 protected static FunkcijaZaMapu funkcijaZaMapu
;
178 public static interface FunkcijaZaMapu
{
179 public int vrednostNa(int x
, int y
);
182 public static void mapa(String naslov
, int sirina
, int visina
, FunkcijaZaMapu funkcijaZaMapu
) {
183 naslovProzora
= naslov
;
186 Prikaz
.funkcijaZaMapu
= funkcijaZaMapu
;
190 protected static Map
<String
, FunkcijaZaPut
> funkcijeZaPuteve
= new LinkedHashMap
<>();
191 protected static Map
<String
, FunkcijaZaVrednostPuta
> funkcijeZaVrednostiPuteva
= new LinkedHashMap
<>();
192 protected static Map
<String
, Paint
> bojeZaPuteve
= new HashMap
<>();
195 public static interface FunkcijaZaPut
{
196 public KorakPuta
korak(int indeks
);
200 public static interface FunkcijaZaVrednostPuta
{
201 public String
vrednost();
204 public static class KorakPuta
{
208 public static KorakPuta
korak(int x
, int y
) {
209 KorakPuta korak
= new KorakPuta();
210 korak
.x
= x
; korak
.y
= y
;
214 public static void put(String naziv
, FunkcijaZaPut funkcijaZaPut
, FunkcijaZaVrednostPuta funkcijaZaVrednostPuta
, Paint boja
) {
215 odradiKasnije(() -> {
216 funkcijeZaPuteve
.remove(naziv
);
217 funkcijeZaVrednostiPuteva
.remove(naziv
);
218 bojeZaPuteve
.remove(naziv
);
219 listaPuteva
.remove(naziv
);
220 Canvas platno
= platnaZaPuteve
.remove(naziv
);
221 centerPane
.getChildren().remove(platno
);
222 if (funkcijaZaPut
!= null && funkcijaZaVrednostPuta
!= null && boja
!= null) {
223 funkcijeZaPuteve
.put(naziv
, funkcijaZaPut
);
224 funkcijeZaVrednostiPuteva
.put(naziv
, funkcijaZaVrednostPuta
);
225 bojeZaPuteve
.put(naziv
, boja
);
226 platno
= new Canvas(Prikaz
.platno
.getWidth(), Prikaz
.platno
.getHeight());
227 platno
.setOpacity(0.5);
228 platno
.getGraphicsContext2D().setLineCap(StrokeLineCap
.ROUND
);
229 platno
.getGraphicsContext2D().setLineJoin(StrokeLineJoin
.ROUND
);
230 platnaZaPuteve
.put(naziv
, platno
);
231 centerPane
.getChildren().add(1, platno
);
232 listaPuteva
.add(naziv
);
238 public static <T
> void put(String naziv
, List
<T
> lista
, Function
<T
, Integer
> x
, Function
<T
, Integer
> y
, FunkcijaZaVrednostPuta funkcijaZaVrednostPuta
, Paint boja
) {
239 FunkcijaZaPut fja
= (int indeks
) -> {
241 T element
= lista
.get(indeks
);
242 return korak(x
.apply(element
), y
.apply(element
));
243 } catch (IndexOutOfBoundsException e
) {
247 put(naziv
, fja
, funkcijaZaVrednostPuta
, boja
);
250 public static void osveziPut(String naziv
) {
251 odradiKasnije(() -> {
253 listaPuteva
.set(listaPuteva
.indexOf(naziv
), naziv
);
262 protected static StackPane centerPane
;
263 protected static ListView
<String
> listView
;
264 protected static ObservableList
<String
> listaPuteva
= FXCollections
.observableArrayList();
267 public void start(Stage primaryStage
) {
268 Label labelPutevi
= new Label("Putevi:");
269 listView
= new ListView
<>(listaPuteva
);
270 listView
.setCellFactory(l
-> new ListCell
<String
>() {
271 public void updateItem(String naziv
, boolean empty
) {
272 super.updateItem(naziv
, empty
);
273 if (empty
|| naziv
== null) {
277 Circle icon
= new Circle(8);
278 icon
.setFill(bojeZaPuteve
.get(naziv
));
280 FunkcijaZaVrednostPuta fja
= funkcijeZaVrednostiPuteva
.get(naziv
);
282 setText(naziv
+ ": " + fja
.vrednost());
283 } catch (RuntimeException e
) {
289 Label labelAnimacija
= new Label();
290 Slider slider
= new Slider(0, 4, 2);
291 Button button
= new Button(">");
292 osveziPanelZaAnimaciju(labelAnimacija
, button
, slider
.getValue());
293 slider
.valueProperty().addListener((value
, oldValue
, newValue
) -> {
294 osveziPanelZaAnimaciju(labelAnimacija
, button
, newValue
.doubleValue());
296 button
.setOnAction(e
-> {
299 button
.setMaxHeight(Double
.MAX_VALUE
);
301 GridPane animationPane
= new GridPane();
302 animationPane
.setHgap(6);
303 animationPane
.setVgap(6);
304 ColumnConstraints column
= new ColumnConstraints();
305 column
.setHgrow(Priority
.ALWAYS
);
306 animationPane
.getColumnConstraints().add(column
);
307 animationPane
.add(labelAnimacija
, 0, 0);
308 animationPane
.add(slider
, 0, 1);
309 animationPane
.add(button
, 1, 0, 1, 2);
311 VBox rightPane
= new VBox();
312 rightPane
.setPadding(new Insets(12, 12, 12, 12));
313 rightPane
.setSpacing(6);
314 rightPane
.getChildren().add(labelPutevi
);
315 listView
.setPrefHeight(0);
316 VBox
.setVgrow(listView
, Priority
.ALWAYS
);
317 rightPane
.getChildren().add(listView
);
318 VBox
.setMargin(animationPane
, new Insets(6, 0, 0, 0));
319 rightPane
.getChildren().add(animationPane
);
321 platno
= new Canvas(ukupnaDuzina(sirinaMape
), ukupnaDuzina(visinaMape
));
323 centerPane
= new StackPane(platno
);
325 BorderPane rootPane
= new BorderPane();
326 rootPane
.setCenter(centerPane
);
327 rootPane
.setRight(rightPane
);
328 Scene scene
= new Scene(rootPane
);
330 primaryStage
.setTitle(naslovProzora
+ " - " + sirinaMape
+ " x " + visinaMape
+ "");
331 primaryStage
.setAlwaysOnTop(true);
332 primaryStage
.setResizable(false);
333 primaryStage
.setOnCloseRequest(e
-> podesiVreme(0));
334 primaryStage
.setScene(scene
);
339 protected static void osveziPanelZaAnimaciju(Label labela
, Button dugme
, double vrednost
) {
340 long vreme
= podesiVreme(vrednost
);
341 String tekst
= "Brzina animacije: " + String
.format("%.2f", vreme
/ 1000.0) + "s";
342 dugme
.setVisible(vreme
>= 1000);
343 labela
.setText(tekst
);
350 protected static Canvas platno
;
351 protected static Map
<String
, Canvas
> platnaZaPuteve
= new LinkedHashMap
<>();
353 protected static void osveziMapu() {
354 crtajMapu(platno
.getGraphicsContext2D(), platno
.getWidth(), platno
.getHeight());
357 protected static void crtajMapu(GraphicsContext gc
, double sirina
, double visina
) {
358 gc
.setTextAlign(TextAlignment
.CENTER
);
359 gc
.setTextBaseline(VPos
.CENTER
);
361 crtajOkvir(gc
, sirina
, visina
);
362 for (int j
= 0; j
< visinaMape
; j
++) {
363 for (int i
= 0; i
< sirinaMape
; i
++) {
364 int sadrzaj
= funkcijaZaMapu
.vrednostNa(i
, j
);
365 Paint bojaPozadina
= bojaPoljaPozadina
.get(sadrzaj
);
366 Paint bojaTekst
= bojaPoljaTekst
.get(sadrzaj
);
367 crtajPolje(gc
, i
, j
, bojaPozadina
, bojaTekst
, "" + sadrzaj
);
372 protected static void crtajOkvir(GraphicsContext gc
, double sirina
, double visina
) {
373 gc
.setFill(bojaPozadine
);
374 gc
.fillRect(0, 0, sirina
, visina
);
375 if (debljinaOkvira
<= 0) {
378 gc
.setFill(bojaOkvira
);
379 gc
.fillRoundRect(x(-debljinaOkvira
), x(-debljinaOkvira
), w(sirinaMape
+ 2 * debljinaOkvira
), w(visinaMape
+ 2 * debljinaOkvira
), r(), r());
380 gc
.setFill(bojaPozadine
);
381 gc
.fillRoundRect(x(-1, 1), x(-1, 1), w(sirinaMape
, 2), w(visinaMape
, 2), r(), r());
384 protected static void crtajPolje(GraphicsContext gc
, int x
, int y
, Paint bojaPozadina
, Paint bojaTekst
, String tekst
) {
385 if (bojaPozadina
!= null) {
386 gc
.setFill(bojaPozadina
);
387 gc
.fillRoundRect(x(x
), x(y
), w(1), w(1), r(), r());
389 if (tekst
!= null && bojaTekst
!= null) {
390 gc
.setFill(bojaTekst
);
391 gc
.fillText(tekst
, x(x
, 0.5), x(y
, 0.5));
395 protected static void crtajPut(String naziv
) {
396 Canvas platno
= platnaZaPuteve
.get(naziv
);
397 GraphicsContext gc
= platno
.getGraphicsContext2D();
398 gc
.clearRect(0, 0, platno
.getWidth(), platno
.getHeight());
399 FunkcijaZaPut fja
= funkcijeZaPuteve
.get(naziv
);
400 Paint boja
= bojeZaPuteve
.get(naziv
);
401 double debljina
= debljinaPuta
;
402 List
<KorakPuta
> koraci
= new ArrayList
<>();
403 int i
= 0; KorakPuta korak
;
404 while ((korak
= fja
.korak(i
++)) != null) {
407 crtajPut(gc
, koraci
, boja
, debljina
);
410 protected static void crtajPut(GraphicsContext gc
, List
<KorakPuta
> koraci
, Paint boja
, double debljina
) {
412 gc
.setLineWidth(debljina
);
413 if (koraci
.size() == 1) {
414 KorakPuta k
= koraci
.get(0);
416 gc
.fillOval(k(k
.x
) - debljina
/ 2, k(k
.y
) - debljina
/ 2, debljina
, debljina
);
418 for (int j
= 1; j
< koraci
.size(); j
++) {
419 KorakPuta k1
= koraci
.get(j
- 1);
420 KorakPuta k2
= koraci
.get(j
);
421 gc
.strokeLine(k(k1
.x
), k(k1
.y
), k(k2
.x
), k(k2
.y
));
429 protected static boolean nekoCeka
= false;
430 protected static long vremeCekanja
= 1000;
432 protected static synchronized void cekajAkoTreba() {
433 long pocetak
= System
.currentTimeMillis();
434 if (vremeCekanja
== 0) {
439 boolean bioPrekid
= Thread
.interrupted();
440 while (nekoCeka
&& (vreme
= pocetak
+ vremeCekanja
- System
.currentTimeMillis()) > 0) {
442 Prikaz
.class.wait(vreme
);
443 } catch (InterruptedException e
) {
448 Thread
.currentThread().interrupt();
453 protected static synchronized void podesiVreme(long novoVremeCekanja
) {
454 vremeCekanja
= novoVremeCekanja
;
455 Prikaz
.class.notify();
458 protected static synchronized void zavrsiCekanje() {
460 Prikaz
.class.notify();
463 protected static long podesiVreme(double stepen
) {
469 long vrednost
= (long) Math
.pow(10, stepen
);
470 podesiVreme(vrednost
);
478 protected static void pokreni() {
480 Runnable launcher
= () -> {
481 launch(new String
[] {});
483 new Thread(launcher
).start();
486 protected static void odradiKasnije(Runnable zadatak
) {
487 Platform
.runLater(zadatak
);