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
.scene
.Scene
;
15 import javafx
.scene
.canvas
.Canvas
;
16 import javafx
.scene
.canvas
.GraphicsContext
;
17 import javafx
.scene
.control
.Button
;
18 import javafx
.scene
.control
.Label
;
19 import javafx
.scene
.control
.ListCell
;
20 import javafx
.scene
.control
.ListView
;
21 import javafx
.scene
.control
.Slider
;
22 import javafx
.scene
.layout
.BorderPane
;
23 import javafx
.scene
.layout
.ColumnConstraints
;
24 import javafx
.scene
.layout
.GridPane
;
25 import javafx
.scene
.layout
.Priority
;
26 import javafx
.scene
.layout
.StackPane
;
27 import javafx
.scene
.layout
.VBox
;
28 import javafx
.scene
.paint
.Color
;
29 import javafx
.scene
.paint
.Paint
;
30 import javafx
.scene
.shape
.Circle
;
31 import javafx
.scene
.shape
.StrokeLineCap
;
32 import javafx
.scene
.shape
.StrokeLineJoin
;
33 import javafx
.scene
.text
.Font
;
34 import javafx
.scene
.text
.FontWeight
;
35 import javafx
.scene
.text
.TextAlignment
;
36 import javafx
.stage
.Stage
;
38 public class Prikaz
extends Application
{
40 public static final Color STVARNO_BELA
= Color
.hsb(0, 0, 1.0);
41 public static final Color BELA
= Color
.hsb(0, 0, 0.95);
42 public static final Color SVETLO_SIVA
= Color
.hsb(0, 0, 0.8);
43 public static final Color SIVA
= Color
.hsb(0, 0, 0.6);
44 public static final Color TAMNO_SIVA
= Color
.hsb(0, 0, 0.4);
45 public static final Color CRNA
= Color
.hsb(0, 0, 0.2);
46 public static final Color STVARNO_CRNA
= Color
.hsb(0, 0, 0.0);
48 public static final Color SVETLO_CRVENA
= Color
.hsb( 0, 0.2, 1.0);
49 public static final Color SVETLO_NARANDZASTA
= Color
.hsb( 30, 0.2, 1.0);
50 public static final Color SVETLO_ZUTA
= Color
.hsb( 60, 0.2, 1.0);
51 public static final Color SVETLO_ZELENA
= Color
.hsb(120, 0.2, 1.0);
52 public static final Color SVETLO_TIRKIZNA
= Color
.hsb(180, 0.2, 1.0);
53 public static final Color SVETLO_AZURNA
= Color
.hsb(210, 0.2, 1.0);
54 public static final Color SVETLO_PLAVA
= Color
.hsb(240, 0.2, 1.0);
55 public static final Color SVETLO_PURPURNA
= Color
.hsb(270, 0.2, 1.0);
56 public static final Color SVETLO_LJUBICASTA
= Color
.hsb(300, 0.2, 1.0);
57 public static final Color SVETLO_RUZICASTA
= Color
.hsb(330, 0.2, 1.0);
59 public static final Color CRVENA
= Color
.hsb( 0, 0.9, 0.8);
60 public static final Color NARANDZASTA
= Color
.hsb( 30, 0.9, 0.8);
61 public static final Color ZUTA
= Color
.hsb( 60, 0.9, 0.8);
62 public static final Color ZELENA
= Color
.hsb(120, 0.9, 0.8);
63 public static final Color TIRKIZNA
= Color
.hsb(180, 0.9, 0.8);
64 public static final Color AZURNA
= Color
.hsb(210, 0.9, 0.8);
65 public static final Color PLAVA
= Color
.hsb(240, 0.9, 0.8);
66 public static final Color PURPURNA
= Color
.hsb(270, 0.9, 0.8);
67 public static final Color LJUBICASTA
= Color
.hsb(300, 0.9, 0.8);
68 public static final Color RUZICASTA
= Color
.hsb(330, 0.9, 0.8);
70 public static final Color TAMNO_CRVENA
= Color
.hsb( 0, 0.8, 0.4);
71 public static final Color TAMNO_NARANDZASTA
= Color
.hsb( 30, 0.8, 0.4);
72 public static final Color TAMNO_ZUTA
= Color
.hsb( 60, 0.8, 0.4);
73 public static final Color TAMNO_ZELENA
= Color
.hsb(120, 0.8, 0.4);
74 public static final Color TAMNO_TIRKIZNA
= Color
.hsb(180, 0.8, 0.4);
75 public static final Color TAMNO_AZURNA
= Color
.hsb(210, 0.8, 0.4);
76 public static final Color TAMNO_PLAVA
= Color
.hsb(240, 0.8, 0.4);
77 public static final Color TAMNO_PURPURNA
= Color
.hsb(270, 0.8, 0.4);
78 public static final Color TAMNO_LJUBICASTA
= Color
.hsb(300, 0.8, 0.4);
79 public static final Color TAMNO_RUZICASTA
= Color
.hsb(330, 0.8, 0.4);
85 protected static Paint bojaPozadine
= BELA
;
86 protected static Paint bojaOkvira
= CRNA
;
87 protected static Map
<Integer
, Paint
> bojaPoljaPozadina
= new HashMap
<>();
88 protected static Map
<Integer
, Paint
> bojaPoljaTekst
= new HashMap
<>();
89 protected static Font font
= Font
.font("Arial", FontWeight
.BOLD
, 12);
91 public static void boja(Paint pozadina
, Paint okvir
) {
92 bojaPozadine
= pozadina
;
96 public static void boja(int vrednost
, Paint bojaPozadine
, Paint bojaTeksta
) {
97 if (bojaPozadine
== null) {
98 bojaPoljaPozadina
.remove(vrednost
);
100 bojaPoljaPozadina
.put(vrednost
, bojaPozadine
);
101 if (bojaTeksta
== null) {
102 bojaPoljaTekst
.remove(vrednost
);
104 bojaPoljaTekst
.put(vrednost
, bojaTeksta
);
107 public static void boja(int vrednostMin
, int vrednostMax
, Color bojaMin
, Color bojaMax
, Paint bojaTeksta
) {
108 if (bojaMin
== null || bojaMax
== null) {
109 throw new IllegalArgumentException();
111 int n
= vrednostMax
- vrednostMin
;
112 for (int i
= 0; i
<= n
; i
++) {
113 int vrednost
= vrednostMin
+ i
;
114 bojaPoljaPozadina
.put(vrednost
, bojaMin
.interpolate(bojaMax
, (double) (i
) / n
));
115 if (bojaTeksta
== null) {
116 bojaPoljaTekst
.remove(vrednost
);
118 bojaPoljaTekst
.put(vrednost
, bojaTeksta
);
126 private static double velicinaPolja
= 32;
127 private static double velicinaRazmaka
= 4;
128 private static int debljinaOkvira
= 0;
129 private static double debljinaPuta
= velicinaPolja
/ 2;
131 public static void velicina(double polje
, double razmak
, int okvir
) {
132 velicinaPolja
= polje
;
133 velicinaRazmaka
= razmak
;
134 debljinaOkvira
= okvir
;
135 debljinaPuta
= velicinaPolja
/ 2;
138 protected static double ukupnaDuzina(int brojPolja
) {
139 return x(brojPolja
+ debljinaOkvira
, 0.0);
142 protected static double x(int indeks
, double delta
) {
143 indeks
= indeks
+ debljinaOkvira
;
144 return indeks
* (velicinaPolja
+ velicinaRazmaka
) + velicinaRazmaka
+ velicinaPolja
* delta
;
147 protected static double x(int indeks
) {
148 return x(indeks
, 0.0);
151 protected static double k(int indeks
) {
152 return x(indeks
, 0.5);
155 protected static double w(int count
, double delta
) {
156 return (velicinaPolja
+ velicinaRazmaka
) * count
+ velicinaRazmaka
* (delta
- 1);
159 protected static double w(int count
) {
163 protected static double r() {
164 return 2 * velicinaRazmaka
;
171 protected static String naslovProzora
;
172 protected static int sirinaMape
;
173 protected static int visinaMape
;
174 protected static FunkcijaZaMapu funkcijaZaMapu
;
177 public static interface FunkcijaZaMapu
{
178 public int vrednostNa(int x
, int y
);
181 public static void mapa(String naslov
, int sirina
, int visina
, FunkcijaZaMapu funkcijaZaMapu
) {
182 naslovProzora
= naslov
;
185 Prikaz
.funkcijaZaMapu
= funkcijaZaMapu
;
189 protected static Map
<String
, FunkcijaZaPut
> funkcijeZaPuteve
= new LinkedHashMap
<>();
190 protected static Map
<String
, FunkcijaZaVrednostPuta
> funkcijeZaVrednostiPuteva
= new LinkedHashMap
<>();
191 protected static Map
<String
, Paint
> bojeZaPuteve
= new HashMap
<>();
194 public static interface FunkcijaZaPut
{
195 public KorakPuta
korak(int indeks
);
199 public static interface FunkcijaZaVrednostPuta
{
200 public String
vrednost();
203 public static class KorakPuta
{
207 public static KorakPuta
korak(int x
, int y
) {
208 KorakPuta korak
= new KorakPuta();
209 korak
.x
= x
; korak
.y
= y
;
213 public static void put(String naziv
, FunkcijaZaPut funkcijaZaPut
, FunkcijaZaVrednostPuta funkcijaZaVrednostPuta
, Paint boja
) {
214 funkcijeZaPuteve
.remove(naziv
);
215 funkcijeZaVrednostiPuteva
.remove(naziv
);
216 bojeZaPuteve
.remove(naziv
);
217 odradiKasnije(() -> {
218 listaPuteva
.remove(naziv
);
219 Canvas platno
= platnaZaPuteve
.remove(naziv
);
220 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 odradiKasnije(() -> {
227 Canvas platno
= new Canvas(Prikaz
.platno
.getWidth(), Prikaz
.platno
.getHeight());
228 platno
.setOpacity(0.5);
229 platno
.getGraphicsContext2D().setLineCap(StrokeLineCap
.ROUND
);
230 platno
.getGraphicsContext2D().setLineJoin(StrokeLineJoin
.ROUND
);
231 platnaZaPuteve
.put(naziv
, platno
);
232 centerPane
.getChildren().add(1, platno
);
233 listaPuteva
.add(naziv
);
239 public static <T
> void put(String naziv
, List
<T
> lista
, Function
<T
, Integer
> x
, Function
<T
, Integer
> y
, FunkcijaZaVrednostPuta funkcijaZaVrednostPuta
, Paint boja
) {
240 FunkcijaZaPut fja
= (int indeks
) -> {
242 T element
= lista
.get(indeks
);
243 return korak(x
.apply(element
), y
.apply(element
));
244 } catch (IndexOutOfBoundsException e
) {
248 put(naziv
, fja
, funkcijaZaVrednostPuta
, boja
);
251 public static void osveziPut(String naziv
) {
252 odradiKasnije(() -> {
254 listaPuteva
.set(listaPuteva
.indexOf(naziv
), naziv
);
263 protected static StackPane centerPane
;
264 protected static ListView
<String
> listView
;
265 protected static ObservableList
<String
> listaPuteva
= FXCollections
.observableArrayList();
268 public void start(Stage primaryStage
) {
269 Label labelPutevi
= new Label("Putevi:");
270 listView
= new ListView
<>(listaPuteva
);
271 listView
.setCellFactory(l
-> new ListCell
<String
>() {
272 public void updateItem(String naziv
, boolean empty
) {
273 super.updateItem(naziv
, empty
);
274 if (empty
|| naziv
== null) {
278 Circle icon
= new Circle(8);
279 icon
.setFill(bojeZaPuteve
.get(naziv
));
281 FunkcijaZaVrednostPuta fja
= funkcijeZaVrednostiPuteva
.get(naziv
);
283 setText(naziv
+ ": " + fja
.vrednost());
284 } catch (RuntimeException e
) {
290 Label labelAnimacija
= new Label();
291 Slider slider
= new Slider(0, 4, 2);
292 Button button
= new Button(">");
293 osveziPanelZaAnimaciju(labelAnimacija
, button
, slider
.getValue());
294 slider
.valueProperty().addListener((value
, oldValue
, newValue
) -> {
295 osveziPanelZaAnimaciju(labelAnimacija
, button
, newValue
.doubleValue());
297 button
.setOnAction(e
-> {
300 button
.setMaxHeight(Double
.MAX_VALUE
);
302 GridPane animationPane
= new GridPane();
303 animationPane
.setHgap(6);
304 animationPane
.setVgap(6);
305 ColumnConstraints column
= new ColumnConstraints();
306 column
.setHgrow(Priority
.ALWAYS
);
307 animationPane
.getColumnConstraints().add(column
);
308 animationPane
.add(labelAnimacija
, 0, 0);
309 animationPane
.add(slider
, 0, 1);
310 animationPane
.add(button
, 1, 0, 1, 2);
312 VBox rightPane
= new VBox();
313 rightPane
.setPadding(new Insets(12, 12, 12, 12));
314 rightPane
.setSpacing(6);
315 rightPane
.getChildren().add(labelPutevi
);
316 listView
.setPrefHeight(0);
317 VBox
.setVgrow(listView
, Priority
.ALWAYS
);
318 rightPane
.getChildren().add(listView
);
319 VBox
.setMargin(animationPane
, new Insets(6, 0, 0, 0));
320 rightPane
.getChildren().add(animationPane
);
322 platno
= new Canvas(ukupnaDuzina(sirinaMape
), ukupnaDuzina(visinaMape
));
324 centerPane
= new StackPane(platno
);
326 BorderPane rootPane
= new BorderPane();
327 rootPane
.setCenter(centerPane
);
328 rootPane
.setRight(rightPane
);
329 Scene scene
= new Scene(rootPane
);
331 primaryStage
.setTitle(naslovProzora
+ " - " + sirinaMape
+ " x " + visinaMape
+ "");
332 primaryStage
.setAlwaysOnTop(true);
333 primaryStage
.setResizable(false);
334 primaryStage
.setOnCloseRequest(e
-> podesiVreme(0));
335 primaryStage
.setScene(scene
);
340 protected static void osveziPanelZaAnimaciju(Label labela
, Button dugme
, double vrednost
) {
341 long vreme
= podesiVreme(vrednost
);
342 String tekst
= "Brzina animacije: " + String
.format("%.2f", vreme
/ 1000.0) + "s";
343 dugme
.setVisible(vreme
>= 1000);
344 labela
.setText(tekst
);
351 protected static Canvas platno
;
352 protected static Map
<String
, Canvas
> platnaZaPuteve
= new LinkedHashMap
<>();
354 protected static void osveziMapu() {
355 crtajMapu(platno
.getGraphicsContext2D(), platno
.getWidth(), platno
.getHeight());
358 protected static void crtajMapu(GraphicsContext gc
, double sirina
, double visina
) {
359 gc
.setTextAlign(TextAlignment
.CENTER
);
360 gc
.setTextBaseline(VPos
.CENTER
);
362 crtajOkvir(gc
, sirina
, visina
);
363 for (int j
= 0; j
< visinaMape
; j
++) {
364 for (int i
= 0; i
< sirinaMape
; i
++) {
365 int sadrzaj
= funkcijaZaMapu
.vrednostNa(i
, j
);
366 Paint bojaPozadina
= bojaPoljaPozadina
.get(sadrzaj
);
367 Paint bojaTekst
= bojaPoljaTekst
.get(sadrzaj
);
368 crtajPolje(gc
, i
, j
, bojaPozadina
, bojaTekst
, "" + sadrzaj
);
373 protected static void crtajOkvir(GraphicsContext gc
, double sirina
, double visina
) {
374 gc
.setFill(bojaPozadine
);
375 gc
.fillRect(0, 0, sirina
, visina
);
376 if (debljinaOkvira
<= 0) {
379 gc
.setFill(bojaOkvira
);
380 gc
.fillRoundRect(x(-debljinaOkvira
), x(-debljinaOkvira
), w(sirinaMape
+ 2 * debljinaOkvira
), w(visinaMape
+ 2 * debljinaOkvira
), r(), r());
381 gc
.setFill(bojaPozadine
);
382 gc
.fillRoundRect(x(-1, 1), x(-1, 1), w(sirinaMape
, 2), w(visinaMape
, 2), r(), r());
385 protected static void crtajPolje(GraphicsContext gc
, int x
, int y
, Paint bojaPozadina
, Paint bojaTekst
, String tekst
) {
386 if (bojaPozadina
!= null) {
387 gc
.setFill(bojaPozadina
);
388 gc
.fillRoundRect(x(x
), x(y
), w(1), w(1), r(), r());
390 if (tekst
!= null && bojaTekst
!= null) {
391 gc
.setFill(bojaTekst
);
392 gc
.fillText(tekst
, x(x
, 0.5), x(y
, 0.5));
396 protected static void crtajPut(String naziv
) {
397 Canvas platno
= platnaZaPuteve
.get(naziv
);
398 GraphicsContext gc
= platno
.getGraphicsContext2D();
399 gc
.clearRect(0, 0, platno
.getWidth(), platno
.getHeight());
400 FunkcijaZaPut fja
= funkcijeZaPuteve
.get(naziv
);
401 Paint boja
= bojeZaPuteve
.get(naziv
);
402 double debljina
= debljinaPuta
;
403 List
<KorakPuta
> koraci
= new ArrayList
<>();
404 int i
= 0; KorakPuta korak
;
405 while ((korak
= fja
.korak(i
++)) != null) {
408 crtajPut(gc
, koraci
, boja
, debljina
);
411 protected static void crtajPut(GraphicsContext gc
, List
<KorakPuta
> koraci
, Paint boja
, double debljina
) {
413 gc
.setLineWidth(debljina
);
414 if (koraci
.size() == 1) {
415 KorakPuta k
= koraci
.get(0);
417 gc
.fillOval(k(k
.x
) - debljina
/ 2, k(k
.y
) - debljina
/ 2, debljina
, debljina
);
419 for (int j
= 1; j
< koraci
.size(); j
++) {
420 KorakPuta k1
= koraci
.get(j
- 1);
421 KorakPuta k2
= koraci
.get(j
);
422 gc
.strokeLine(k(k1
.x
), k(k1
.y
), k(k2
.x
), k(k2
.y
));
430 protected static boolean nekoCeka
= false;
431 protected static long vremeCekanja
= 1000;
433 protected static synchronized void cekajAkoTreba() {
434 long pocetak
= System
.currentTimeMillis();
435 if (vremeCekanja
== 0) {
440 boolean bioPrekid
= Thread
.interrupted();
441 while (nekoCeka
&& (vreme
= pocetak
+ vremeCekanja
- System
.currentTimeMillis()) > 0) {
443 Prikaz
.class.wait(vreme
);
444 } catch (InterruptedException e
) {
449 Thread
.currentThread().interrupt();
454 protected static synchronized void podesiVreme(long novoVremeCekanja
) {
455 vremeCekanja
= novoVremeCekanja
;
456 Prikaz
.class.notify();
459 protected static synchronized void zavrsiCekanje() {
461 Prikaz
.class.notify();
464 protected static long podesiVreme(double stepen
) {
470 long vrednost
= (long) Math
.pow(10, stepen
);
471 podesiVreme(vrednost
);
479 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
);