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 odradiKasnije(() -> {
215 funkcijeZaPuteve
.remove(naziv
);
216 funkcijeZaVrednostiPuteva
.remove(naziv
);
217 bojeZaPuteve
.remove(naziv
);
218 listaPuteva
.remove(naziv
);
219 Canvas platno
= platnaZaPuteve
.remove(naziv
);
220 centerPane
.getChildren().remove(platno
);
221 if (funkcijaZaPut
!= null && funkcijaZaVrednostPuta
!= null && boja
!= null) {
222 funkcijeZaPuteve
.put(naziv
, funkcijaZaPut
);
223 funkcijeZaVrednostiPuteva
.put(naziv
, funkcijaZaVrednostPuta
);
224 bojeZaPuteve
.put(naziv
, boja
);
225 platno
= new Canvas(Prikaz
.platno
.getWidth(), Prikaz
.platno
.getHeight());
226 platno
.setOpacity(0.5);
227 platno
.getGraphicsContext2D().setLineCap(StrokeLineCap
.ROUND
);
228 platno
.getGraphicsContext2D().setLineJoin(StrokeLineJoin
.ROUND
);
229 platnaZaPuteve
.put(naziv
, platno
);
230 centerPane
.getChildren().add(1, platno
);
231 listaPuteva
.add(naziv
);
237 public static <T
> void put(String naziv
, List
<T
> lista
, Function
<T
, Integer
> x
, Function
<T
, Integer
> y
, FunkcijaZaVrednostPuta funkcijaZaVrednostPuta
, Paint boja
) {
238 FunkcijaZaPut fja
= (int indeks
) -> {
240 T element
= lista
.get(indeks
);
241 return korak(x
.apply(element
), y
.apply(element
));
242 } catch (IndexOutOfBoundsException e
) {
246 put(naziv
, fja
, funkcijaZaVrednostPuta
, boja
);
249 public static void osveziPut(String naziv
) {
250 odradiKasnije(() -> {
252 listaPuteva
.set(listaPuteva
.indexOf(naziv
), naziv
);
261 protected static StackPane centerPane
;
262 protected static ListView
<String
> listView
;
263 protected static ObservableList
<String
> listaPuteva
= FXCollections
.observableArrayList();
266 public void start(Stage primaryStage
) {
267 Label labelPutevi
= new Label("Putevi:");
268 listView
= new ListView
<>(listaPuteva
);
269 listView
.setCellFactory(l
-> new ListCell
<String
>() {
270 public void updateItem(String naziv
, boolean empty
) {
271 super.updateItem(naziv
, empty
);
272 if (empty
|| naziv
== null) {
276 Circle icon
= new Circle(8);
277 icon
.setFill(bojeZaPuteve
.get(naziv
));
279 FunkcijaZaVrednostPuta fja
= funkcijeZaVrednostiPuteva
.get(naziv
);
281 setText(naziv
+ ": " + fja
.vrednost());
282 } catch (RuntimeException e
) {
288 Label labelAnimacija
= new Label();
289 Slider slider
= new Slider(0, 4, 2);
290 Button button
= new Button(">");
291 osveziPanelZaAnimaciju(labelAnimacija
, button
, slider
.getValue());
292 slider
.valueProperty().addListener((value
, oldValue
, newValue
) -> {
293 osveziPanelZaAnimaciju(labelAnimacija
, button
, newValue
.doubleValue());
295 button
.setOnAction(e
-> {
298 button
.setMaxHeight(Double
.MAX_VALUE
);
300 GridPane animationPane
= new GridPane();
301 animationPane
.setHgap(6);
302 animationPane
.setVgap(6);
303 ColumnConstraints column
= new ColumnConstraints();
304 column
.setHgrow(Priority
.ALWAYS
);
305 animationPane
.getColumnConstraints().add(column
);
306 animationPane
.add(labelAnimacija
, 0, 0);
307 animationPane
.add(slider
, 0, 1);
308 animationPane
.add(button
, 1, 0, 1, 2);
310 VBox rightPane
= new VBox();
311 rightPane
.setPadding(new Insets(12, 12, 12, 12));
312 rightPane
.setSpacing(6);
313 rightPane
.getChildren().add(labelPutevi
);
314 listView
.setPrefHeight(0);
315 VBox
.setVgrow(listView
, Priority
.ALWAYS
);
316 rightPane
.getChildren().add(listView
);
317 VBox
.setMargin(animationPane
, new Insets(6, 0, 0, 0));
318 rightPane
.getChildren().add(animationPane
);
320 platno
= new Canvas(ukupnaDuzina(sirinaMape
), ukupnaDuzina(visinaMape
));
322 centerPane
= new StackPane(platno
);
324 BorderPane rootPane
= new BorderPane();
325 rootPane
.setCenter(centerPane
);
326 rootPane
.setRight(rightPane
);
327 Scene scene
= new Scene(rootPane
);
329 primaryStage
.setTitle(naslovProzora
+ " - " + sirinaMape
+ " x " + visinaMape
+ "");
330 primaryStage
.setAlwaysOnTop(true);
331 primaryStage
.setResizable(false);
332 primaryStage
.setOnCloseRequest(e
-> podesiVreme(0));
333 primaryStage
.setScene(scene
);
338 protected static void osveziPanelZaAnimaciju(Label labela
, Button dugme
, double vrednost
) {
339 long vreme
= podesiVreme(vrednost
);
340 String tekst
= "Brzina animacije: " + String
.format("%.2f", vreme
/ 1000.0) + "s";
341 dugme
.setVisible(vreme
>= 1000);
342 labela
.setText(tekst
);
349 protected static Canvas platno
;
350 protected static Map
<String
, Canvas
> platnaZaPuteve
= new LinkedHashMap
<>();
352 protected static void osveziMapu() {
353 crtajMapu(platno
.getGraphicsContext2D(), platno
.getWidth(), platno
.getHeight());
356 protected static void crtajMapu(GraphicsContext gc
, double sirina
, double visina
) {
357 gc
.setTextAlign(TextAlignment
.CENTER
);
358 gc
.setTextBaseline(VPos
.CENTER
);
360 crtajOkvir(gc
, sirina
, visina
);
361 for (int j
= 0; j
< visinaMape
; j
++) {
362 for (int i
= 0; i
< sirinaMape
; i
++) {
363 int sadrzaj
= funkcijaZaMapu
.vrednostNa(i
, j
);
364 Paint bojaPozadina
= bojaPoljaPozadina
.get(sadrzaj
);
365 Paint bojaTekst
= bojaPoljaTekst
.get(sadrzaj
);
366 crtajPolje(gc
, i
, j
, bojaPozadina
, bojaTekst
, "" + sadrzaj
);
371 protected static void crtajOkvir(GraphicsContext gc
, double sirina
, double visina
) {
372 gc
.setFill(bojaPozadine
);
373 gc
.fillRect(0, 0, sirina
, visina
);
374 if (debljinaOkvira
<= 0) {
377 gc
.setFill(bojaOkvira
);
378 gc
.fillRoundRect(x(-debljinaOkvira
), x(-debljinaOkvira
), w(sirinaMape
+ 2 * debljinaOkvira
), w(visinaMape
+ 2 * debljinaOkvira
), r(), r());
379 gc
.setFill(bojaPozadine
);
380 gc
.fillRoundRect(x(-1, 1), x(-1, 1), w(sirinaMape
, 2), w(visinaMape
, 2), r(), r());
383 protected static void crtajPolje(GraphicsContext gc
, int x
, int y
, Paint bojaPozadina
, Paint bojaTekst
, String tekst
) {
384 if (bojaPozadina
!= null) {
385 gc
.setFill(bojaPozadina
);
386 gc
.fillRoundRect(x(x
), x(y
), w(1), w(1), r(), r());
388 if (tekst
!= null && bojaTekst
!= null) {
389 gc
.setFill(bojaTekst
);
390 gc
.fillText(tekst
, x(x
, 0.5), x(y
, 0.5));
394 protected static void crtajPut(String naziv
) {
395 Canvas platno
= platnaZaPuteve
.get(naziv
);
396 GraphicsContext gc
= platno
.getGraphicsContext2D();
397 gc
.clearRect(0, 0, platno
.getWidth(), platno
.getHeight());
398 FunkcijaZaPut fja
= funkcijeZaPuteve
.get(naziv
);
399 Paint boja
= bojeZaPuteve
.get(naziv
);
400 double debljina
= debljinaPuta
;
401 List
<KorakPuta
> koraci
= new ArrayList
<>();
402 int i
= 0; KorakPuta korak
;
403 while ((korak
= fja
.korak(i
++)) != null) {
406 crtajPut(gc
, koraci
, boja
, debljina
);
409 protected static void crtajPut(GraphicsContext gc
, List
<KorakPuta
> koraci
, Paint boja
, double debljina
) {
411 gc
.setLineWidth(debljina
);
412 if (koraci
.size() == 1) {
413 KorakPuta k
= koraci
.get(0);
415 gc
.fillOval(k(k
.x
) - debljina
/ 2, k(k
.y
) - debljina
/ 2, debljina
, debljina
);
417 for (int j
= 1; j
< koraci
.size(); j
++) {
418 KorakPuta k1
= koraci
.get(j
- 1);
419 KorakPuta k2
= koraci
.get(j
);
420 gc
.strokeLine(k(k1
.x
), k(k1
.y
), k(k2
.x
), k(k2
.y
));
428 protected static boolean nekoCeka
= false;
429 protected static long vremeCekanja
= 1000;
431 protected static synchronized void cekajAkoTreba() {
432 long pocetak
= System
.currentTimeMillis();
433 if (vremeCekanja
== 0) {
438 boolean bioPrekid
= Thread
.interrupted();
439 while (nekoCeka
&& (vreme
= pocetak
+ vremeCekanja
- System
.currentTimeMillis()) > 0) {
441 Prikaz
.class.wait(vreme
);
442 } catch (InterruptedException e
) {
447 Thread
.currentThread().interrupt();
452 protected static synchronized void podesiVreme(long novoVremeCekanja
) {
453 vremeCekanja
= novoVremeCekanja
;
454 Prikaz
.class.notify();
457 protected static synchronized void zavrsiCekanje() {
459 Prikaz
.class.notify();
462 protected static long podesiVreme(double stepen
) {
468 long vrednost
= (long) Math
.pow(10, stepen
);
469 podesiVreme(vrednost
);
477 protected static void pokreni() {
478 Runnable launcher
= () -> {
479 launch(new String
[] {});
481 new Thread(launcher
).start();
484 protected static void odradiKasnije(Runnable zadatak
) {
485 Platform
.runLater(zadatak
);