From c8e0d487886dbec1e3a994ea36724bbf59f5122a Mon Sep 17 00:00:00 2001
From: Kenneth Russel <kbrussel@alum.mit.edu>
Date: Tue, 9 Oct 2007 07:38:25 +0000
Subject: Integration of Tomas Hrasky's port of basic GLU NURBS functionality
 from C++ to Java, plus example applications, done as part of his Bachelor of
 Science degree at the University of Hradec Králové, Faculty of Informatics
 and Management.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Current state of code is documented in
src/classes/com/sun/opengl/impl/nurbs/README.txt.

Example applications require Java 1.5 and are not currently built by
default. Specify -Djogl.nurbs=1 during jogl-demos build with a 1.5
javac on the PATH to build them. Dependent jars are copied to build
output directory.

Deleted old partially-complete GLU NURBS port.


git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@223 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
---
 src/demos/nurbs/curveapp/ActListener.java        | 114 ++++
 src/demos/nurbs/curveapp/Curve.java              | 313 +++++++++++
 src/demos/nurbs/curveapp/CurveApp.java           | 659 +++++++++++++++++++++++
 src/demos/nurbs/curveapp/CurveMouseListener.java | 180 +++++++
 src/demos/nurbs/curveapp/GLListener.java         | 141 +++++
 src/demos/nurbs/curveapp/MyFloat.java            |  55 ++
 src/demos/nurbs/curveapp/SpinnerListener.java    |  47 ++
 7 files changed, 1509 insertions(+)
 create mode 100755 src/demos/nurbs/curveapp/ActListener.java
 create mode 100755 src/demos/nurbs/curveapp/Curve.java
 create mode 100755 src/demos/nurbs/curveapp/CurveApp.java
 create mode 100755 src/demos/nurbs/curveapp/CurveMouseListener.java
 create mode 100755 src/demos/nurbs/curveapp/GLListener.java
 create mode 100755 src/demos/nurbs/curveapp/MyFloat.java
 create mode 100755 src/demos/nurbs/curveapp/SpinnerListener.java

(limited to 'src/demos/nurbs/curveapp')

diff --git a/src/demos/nurbs/curveapp/ActListener.java b/src/demos/nurbs/curveapp/ActListener.java
new file mode 100755
index 0000000..52e89b8
--- /dev/null
+++ b/src/demos/nurbs/curveapp/ActListener.java
@@ -0,0 +1,114 @@
+package demos.nurbs.curveapp;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+import demos.nurbs.icons.*;
+
+/**
+ * Class reacting to events from toolbar and menu
+ * Třída reagující na události z nástrojové lišty a menu
+ * @author Tomáš Hráský
+ *
+ */
+@SuppressWarnings("serial")
+public class ActListener extends AbstractAction
+{
+
+  /**
+   * Parent window
+   * Odkaz na rodičovské okno
+   */
+  private CurveApp app;
+  /**
+   * File chooser object
+   * Objekt pro výběr souboru
+   */
+  private JFileChooser fc;
+
+  /**
+   * Creates instance of object with pointer to parent window
+   * Vytvoří instanci objektu s odkazem na rodičovské okno
+   * @param app parent window
+   */
+  public ActListener(CurveApp app) {
+    this.app=app;
+    fc=new JFileChooser("./");
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+   */
+  public void actionPerformed(ActionEvent e) {
+		
+		
+    if(e.getActionCommand()==CurveApp.PRIDAT_AC){
+				
+    }else if(e.getActionCommand()==CurveApp.SMAZAT_AC){
+			
+    }else if(e.getActionCommand()==CurveApp.UZAVRENY_AC){
+      app.uzavernyKV();
+    }else if(e.getActionCommand()==CurveApp.OTEVRENY_AC){
+      app.otevrenyKV();
+    }else if(e.getActionCommand()==CurveApp.ULOZIT_AC){
+      if(fc.showSaveDialog(app)==JFileChooser.APPROVE_OPTION){
+        Curve.getInstance().persist(fc.getSelectedFile());
+      }
+    }else if(e.getActionCommand()==CurveApp.NACIST_AC){
+      if(fc.showOpenDialog(app)==JFileChooser.APPROVE_OPTION){
+        try {
+          Curve.getInstance().unPersist(fc.getSelectedFile());
+          app.updateGLCanvas();
+          app.selectMoveButt();
+          app.updateJKnotSlider();
+        } catch (Exception e1) {
+          //JOptionPane.showMessageDialog(app,"Chyba při načítání ze souboru","Chyba",JOptionPane.ERROR_MESSAGE);
+          JOptionPane.showMessageDialog(app,"Error loading file","Error",JOptionPane.ERROR_MESSAGE);
+        }
+      }
+    }else if(e.getActionCommand()==CurveApp.NOVA_AC){
+      Curve.getInstance().clear();
+      app.getMouseListener().setBodIndex(-1);
+      Curve.getInstance().setBodIndex(-1);
+      app.updateGLCanvas();
+      app.updateJKnotSlider();
+    }else if(e.getActionCommand()==CurveApp.EXIT_AC){
+      //TODO exit confirmation ?
+      System.exit(0);
+    }else if(e.getActionCommand()==CurveApp.STUPEN_AC){
+      try{
+        //String retval = JOptionPane.showInputDialog(null,"Zadejte stupeň křivky",new Integer(Curve.getInstance().getOrder()));
+        String retval = JOptionPane.showInputDialog(null,"Curve degree",new Integer(Curve.getInstance().getOrder()));
+        if(retval!=null){
+          int stupen=(new Integer(retval)).intValue();
+          Curve.getInstance().setOrder(stupen);
+          Curve.getInstance().setIsCurveFinished(false);
+        }
+      }catch (NumberFormatException ex){
+        //JOptionPane.showMessageDialog(null,"Chybný formát přirozeného čísla","Chyba!",JOptionPane.ERROR_MESSAGE);
+        JOptionPane.showMessageDialog(null,"Wrong natural number format","Error!",JOptionPane.ERROR_MESSAGE);
+      }
+    }else if(e.getActionCommand()==CurveApp.INFO_AC){
+      /*
+        JOptionPane.showMessageDialog(null,"Ukázková aplikace rozšířené funkcionality knihovny JOGL\n" +
+        "Autor: Tomáš Hráský\n" +
+        "Součást bakalářské práce na téma Softwarová implementace NURBS křivek a ploch\n" +
+        "2007 Fakulta Informatiky a Managementu UHK\n" +
+        "Pro serializaci objektů využívá open source framework Simple XML - http://simple.sourceforge.net/","O aplikaci",JOptionPane.INFORMATION_MESSAGE,IconFactory.getIcon("demos/nurbs/icons/info.png"));
+      */
+      JOptionPane.showMessageDialog(null,"Example aplication of extended functionality JOGL library\n" +
+                                    "Author: Tomáš Hráský\n" +
+                                    "Part of bachelor's degree thesis Software implementation of NURBS curves and surfaces\n" +
+                                    "2007 Faculty of Informatics and Management University of Hradec Králové\n" +
+                                    "Simple XML framework is used for object serialization - http://simple.sourceforge.net/","About",JOptionPane.INFORMATION_MESSAGE,IconFactory.getIcon("demos/nurbs/icons/info.png"));
+    }
+		
+    app.getMouseListener().setActionType(e.getActionCommand());
+		
+		
+  }
+}
diff --git a/src/demos/nurbs/curveapp/Curve.java b/src/demos/nurbs/curveapp/Curve.java
new file mode 100755
index 0000000..b772973
--- /dev/null
+++ b/src/demos/nurbs/curveapp/Curve.java
@@ -0,0 +1,313 @@
+package demos.nurbs.curveapp;
+
+import java.io.File;
+import java.util.Vector;
+
+import simple.xml.Element;
+import simple.xml.ElementList;
+import simple.xml.Root;
+import simple.xml.Serializer;
+import simple.xml.load.Persister;
+
+/**
+ * Třída definice NURBS křivky, vystavěna podle návrhového vzoru Singleton
+ * @author Tomáš Hráský
+ *
+ */
+@Root(name="curve")
+public class Curve
+{
+  /**
+   * Odkaz na instanci třídy
+   */
+  private static Curve singleton;
+  /**
+   * Indikuje, zda je zadání křivky kompletní
+   */
+  @Element(name="finished")
+    private boolean isCurveFinished;
+
+  /**
+   * Index aktuálního vybraného řídícího bodu
+   */
+  private int bodIndex = -1;
+
+  /**
+   * Stupeň křivky
+   */
+  @Element(name="order")
+    private int order=3;
+	
+  /**
+   * Pole souřadnic řídícíh bodů 
+   * 
+   */
+  private float[] ctrlPoints;
+	
+  /**
+   * Pole hodnot uzlového vektoru
+   */
+  private	float knots[];
+
+  /**
+   * Kolekce vektor pro persistenci souřadnic řídících bodů
+   */
+  @ElementList(name="ctrlpoints",type=MyFloat.class)
+    private Vector<MyFloat> ctrlVector;
+	
+  /**
+   * Kolekce vektor pro persistenci uzlového vektoru
+   */
+  @ElementList(name="knots",type=MyFloat.class)
+    private Vector<MyFloat> knotVector;
+	
+  /**
+   * Vytvoří prázdnou definici křivky
+   */
+  public void clear(){
+    isCurveFinished=false;
+    ctrlPoints=new float[0];
+    knots=new float[0];
+    order=3;
+  }
+	
+  /**
+   * Pomocí framweorku Simple serializuje definici křivky do XML souboru
+   * @param f soubor pro uložení
+   */
+  public void persist(File f){
+    ctrlVector=new Vector<MyFloat>(ctrlPoints.length);
+    knotVector=new Vector<MyFloat>(knots.length);
+		
+    for(Float ff:ctrlPoints)
+      ctrlVector.add(new MyFloat(ff));
+		
+    for(Float ff:knots)
+      knotVector.add(new MyFloat(ff));
+		
+    Serializer s=new Persister(); 
+    try {
+      System.out.println("ukládám");
+      s.write(Curve.getInstance(),f);
+    } catch (Exception e1) {
+      e1.printStackTrace();
+    }
+
+
+  }
+	
+  /**
+   * Vytvoří pomocí frameworku Simple křivku z definice uložené v XML souboru 
+   * @param f soubor,z něhož se má definice načíst
+   * @throws Exception chyba při čtení ze souboru
+   */
+  public void unPersist(File f) throws Exception{
+    Serializer s=new Persister();
+    Curve c=s.read(Curve.class,f);
+    initFromCurve(c);
+  }
+	
+  /**
+   * Inicializuje objekt podle jiného objektu typu Curve
+   * @param c referenční objekt - křivka
+   */
+  private void initFromCurve(Curve c) {
+    this.order=c.getOrder();
+    this.ctrlPoints=new float[c.getCtrlVector().size()];
+    this.knots=new float[c.getKnotVector().size()];
+    int i=0;
+    for(MyFloat f:c.getCtrlVector())
+      ctrlPoints[i++]=f.getValue();
+    i=0;
+    for(MyFloat f:c.getKnotVector())
+      knots[i++]=f.getValue();
+		
+    this.isCurveFinished=c.isCurveFinished();
+  }
+
+  /**
+   * Konstruktor, nastaví prázdné hodnoty polí definujících NURBS křivku
+   */
+  private Curve(){
+    ctrlPoints=new float[0];
+    knots=new float[0];
+    isCurveFinished=false;
+  }
+	
+  /**
+   * Vrací instanci třídy (podle návrhového vzoru Singleton)
+   * @return instance třídy Curve
+   */
+  public static Curve getInstance() {
+    if (singleton == null)
+      singleton = new Curve();
+    return singleton;
+
+  }
+	
+  /**
+   * Vrací pole uzlového vektoru
+   * @return pole hodnot uzlového vektoru
+   */
+  public float[] getKnots() {
+    return this.knots;
+  }
+
+  /**
+   * Vrací pole s hodnotami souřadnic řídících bodů
+   * @return pole souřadnic řídících bodů
+   */
+  public float[] getCtrlPoints() {
+    return this.ctrlPoints;
+  }
+
+  /**
+   * Vrací stupeň NURBS křivky
+   * @return stupeň NURBS křivky
+   */
+  public int getOrder() {
+    return this.order;
+  }
+
+  /**
+   * Vrací index aktuálně vybraného řídícího bodu
+   * @return index aktuálně vybraného řídícího bodu
+   */
+  public int getBodIndex() {
+    return bodIndex;
+  }
+
+  /**
+   * Nastavuje index požadovaného aktuálně vybraného řídícího bodu
+   * @param bodIndex index požadovaného aktuálně vybraného řídícího bodu
+   */
+  public void setBodIndex(int bodIndex) {
+    this.bodIndex = bodIndex;
+  }
+	
+  /**
+   * Vrací X-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu z homogenních souřadnic
+   * @return X-ová souadnice aktuálně vybraného řídícího bodu
+   */
+  public float getActiveX(){
+    if(bodIndex>=0){
+      return ctrlPoints[bodIndex*4]/ctrlPoints[bodIndex*4+3];
+    }
+    else return 0;
+  }
+  /**
+   * Vrací Y-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu z homogenních souřadnic
+   * @return Y-ová souadnice aktuálně vybraného řídícího bodu
+   */
+  public float getActiveY(){
+    if(bodIndex>=0){
+      return ctrlPoints[bodIndex*4+1]/ctrlPoints[bodIndex*4+3];
+    }
+    else return 0;
+  }
+	
+  /**
+   * Vrací váhu aktuálně vybraného řídícího bodu
+   * @return váha aktuálně vybraného řídícího bodu
+   */
+  public float getActiveW(){
+    if(bodIndex>=0){
+      return ctrlPoints[bodIndex*4+3];
+    }
+    else return 0;
+  }
+	
+  /**
+   * Nastavuje X-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu do homogenních souřadnic
+   * @param x X-ová souřadnice aktuálně vybraného řídícího bodu
+   */
+  public void setActiveX(float x){
+    if(bodIndex>=0){
+      ctrlPoints[bodIndex*4]=x*ctrlPoints[bodIndex*4+3];
+    }
+  }
+  /**
+   * Nastavuje Y-ovou souadnici aktuálně vybraného řídícího bodu, přepočítává hodnotu do homogenních souřadnic
+   * @param y Y-ová souřadnice aktuálně vybraného řídícího bodu
+   */
+	
+  public void setActiveY(float y){
+    if(bodIndex>=0){
+      ctrlPoints[bodIndex*4+1]=y*ctrlPoints[bodIndex*4+3];
+    }
+  }
+	
+  /**
+   *Nastavuje váhu aktuálně vybraného řídícího bodu, upravuje hodnoty stávajícíh souřadic vzhledem k váze a použití homogenních souřadnic 
+   * @param w váha aktuálně vybraného řídícího bodu
+   */
+  public void setActiveW(float w){
+    if(bodIndex>=0){
+      float oldW=ctrlPoints[bodIndex*4+3];
+      if(w>0){
+        ctrlPoints[bodIndex*4+3]=w;
+        //úprava souřadnic
+        ctrlPoints[bodIndex*4]=ctrlPoints[bodIndex*4]/oldW*w;
+        ctrlPoints[bodIndex*4+1]=ctrlPoints[bodIndex*4+1]/oldW*w;
+      }
+			
+    }
+  }
+
+  /**
+   * Nastavuje uzlový vektor
+   * @param knots nový uzlový vektor
+   */
+  public void setKnots(float[] knots) {
+    this.knots = knots;
+  }
+
+  /**
+   * Vrací informaci o stavu dokončení definice křvky
+   * @return true pokud je definice křivky kompletní, jinak false
+   */
+  public boolean isCurveFinished() {
+    return isCurveFinished;
+  }
+
+  /**
+   * Nastavuje řídící body
+   * @param ctrlPoints pole souřadnic řídících bodů 
+   */
+  public void setCtrlPoints(float[] ctrlPoints) {
+    this.ctrlPoints = ctrlPoints;
+  }
+
+  /**
+   * Nastavuje stav dokončení definice křivky
+   * @param b stav dokončení definice křivky
+   *
+   */
+  public void setIsCurveFinished(boolean b) {
+    isCurveFinished=b;
+  }
+
+  /**
+   * Vrací vektor souřadnic řídích bodů pro serializaci
+   * @return vektor souřadnic řídících bodů
+   */
+  private Vector<MyFloat> getCtrlVector() {
+    return ctrlVector;
+  }
+
+  /**
+   * Vrací vektor prvků uzlového vektoru pro serializaci
+   * @return vektor prvků uzlového vektoru
+   */
+  private Vector<MyFloat> getKnotVector() {
+    return knotVector;
+  }
+
+  /**
+   * Nastaví stupeň křivky
+   * @param order požadovaný stupeň
+   */
+  public void setOrder(int order) {
+    this.order = order;
+  }
+}
diff --git a/src/demos/nurbs/curveapp/CurveApp.java b/src/demos/nurbs/curveapp/CurveApp.java
new file mode 100755
index 0000000..ff70f68
--- /dev/null
+++ b/src/demos/nurbs/curveapp/CurveApp.java
@@ -0,0 +1,659 @@
+package demos.nurbs.curveapp;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.media.opengl.GLCanvas;
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JSeparator;
+import javax.swing.JSpinner;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.ToolTipManager;
+
+import demos.nurbs.icons.*;
+import demos.nurbs.knotslidercomponent.JKnotSlider;
+
+/**
+ * Main class of application demostrating capabilities of JOGL when working with NURBS curves
+ * Hlavní třída aplikace demonstrující shopnosti knihovny JOGL při práci s NURBS křivkami
+ * @author Tomáš Hráský
+ *
+ */
+@SuppressWarnings("serial")
+public class CurveApp extends JFrame implements ActionListener
+{
+
+  /**
+   * Name of X-coord editing component of actually selected control point
+   * Jméno komponenty pro editaci X-ové souřadnice aktuálního bodu
+   */
+  public static final String X_SPINNER_NAME = "xspinner";
+  /**
+   * Name of Y-coord editing component of actually selected control point
+   * Jméno komponenty pro editaci Y-ové souřadnice aktuálního bodu
+   */
+  public static final String Y_SPINNER_NAME = "yspinner";
+  /**
+   * Name of weight editing component of actually selected control point
+   * Jméno komponenty pro editaci váhy aktuálního bodu
+   */
+  public static final String W_SPINNER_NAME = "wspinner";
+
+  /**
+   * Name of ADD CONTROL POINT event
+   * Jméno události přidání řídícího bodu
+   */
+  public static final String PRIDAT_AC = "PRIDAT";
+	
+  /**
+   * Name of SET CURVE DEGREE event
+   * Jméno události zadání stupně křivky
+   */
+  public static final String STUPEN_AC="STUPEN";
+  /**
+   * Name of DELETE CONTROL POINT event
+   * Jméno události smazání řídícího bodu
+   */
+  public static final String SMAZAT_AC = "SMAZAT";
+  /**
+   * Name of MAKE CLOSED KNOTVECTOR event
+   * Jméno události vytvoření uzavřeného uzlového vektoru
+   */
+  public static final String UZAVRENY_AC = "UZAVRENY";
+  /**
+   * Name of MAKE OPEN (UNIFORM) KNOTVECTOR event
+   * Jméno události vytvoření otevřeného (uniformního) uzlového vektoru
+   */
+  public static final String OTEVRENY_AC = "OTEVRENY";
+  /**
+   * Name of SAVE CURVE event
+   * Jméno události uložení křivky
+   */
+  public static final String ULOZIT_AC = "ULOZIT";
+  /**
+   * Name of LOAD CURVE event
+   * Jméno události načetení uložené definice křivky
+   */
+  public static final String NACIST_AC = "NACIST";
+  /**
+   * Name of MOVE CONTROL POINT event
+   * Jméno události pohybu řídícího bodu
+   */
+  private static final String MOVE_AC = "MOVE";
+
+  /**
+   * Name of CREATE NEW CURVE event
+   * Jméno události vytvoření nové křivky
+   */
+  static final String NOVA_AC = "NEWCURVE";
+
+  /**
+   * Name of EXIT APP event
+   * Jméno události ukončení aplikace
+   */
+  public static final String EXIT_AC = "EXIT";
+  /**
+   * Name of SHOW ABOUT event
+   * Jméno události zobrazení okna o aplikaci
+   */
+  public static final String INFO_AC = "INFO";
+
+  /**
+   * OpenGL canvas
+   * Plátno pro vykreslování pomocí OpenGL
+   */
+  private GLCanvas glCanvas;
+
+  /**
+   * X-coord editing component
+   * Komponenta pro editaci X-ové souřadnice aktuálního bodu
+   */
+  private JSpinner xSpinner;
+  /**
+   * Y-coord editing component
+   * Komponenta pro editaci Y-ové souřadnice aktuálního bodu
+   */
+  private JSpinner ySpinner;
+  /**
+   * Weight editing component
+   * Komponenta pro editaci váhy aktuálního bodu
+   */
+  private JSpinner wSpinner;
+
+  /**
+   * Mouse events listener
+   * Listener událostí myši
+   */
+  private CurveMouseListener mouseListener;
+
+  /**
+   * Knot vector editing component
+   * Komponenta pro editaci uzlového vektoru
+   */
+  private JKnotSlider knotSlider;
+
+  /**
+   * Start "move control point" mode
+   * Tlačítko pro zapnutí módu pohybu řídících bodů
+   */
+  private JToggleButton moveTB;
+
+  /**
+   * Constructor, initializes GUI
+   * Konstruktor, vytvoří grafické uživatelské rozhraní
+   */
+  public CurveApp() {
+    super("Tomáš Hráský - example application demonstrating GLU NURBS capabilites - JOGL");
+    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+    initGUI();
+  }
+
+  /**
+   * GUI initialization
+   * Inicializace grafického uživatelského rozhraní
+   */
+  private void initGUI() {
+    JPopupMenu.setDefaultLightWeightPopupEnabled(false);
+    ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
+		
+    this.glCanvas = new GLCanvas();
+    glCanvas.setSize(new Dimension(750, 500));
+    glCanvas.addGLEventListener(new GLListener());
+    mouseListener = new CurveMouseListener(this);
+    glCanvas.addMouseListener(mouseListener);
+    glCanvas.addMouseMotionListener(mouseListener);
+    setLayout(new GridBagLayout());
+    GridBagConstraints c = new GridBagConstraints();
+    c.fill = GridBagConstraints.BOTH;
+
+    c.gridy = 0;
+    c.gridwidth = GridBagConstraints.REMAINDER;
+
+    ActListener listener = new ActListener(this);
+
+    JMenuBar menuBar = new JMenuBar();
+    getContentPane().add(menuBar, c);
+
+    //JMenu aplikaceMenu = new JMenu("Aplikace");
+    JMenu aplikaceMenu = new JMenu("Application");
+    menuBar.add(aplikaceMenu);
+		
+    //JMenuItem aboutMI=new JMenuItem("O aplikaci");
+    JMenuItem aboutMI=new JMenuItem("About");
+    aboutMI.setActionCommand(INFO_AC);
+    aboutMI.addActionListener(listener);
+    aplikaceMenu.add(aboutMI);
+		
+    aplikaceMenu.add(new JSeparator());
+		
+    //JMenuItem konecMI=new JMenuItem("Ukončit");
+    JMenuItem konecMI=new JMenuItem("Exit");
+    konecMI.addActionListener(listener);
+    konecMI.setActionCommand(EXIT_AC);
+    aplikaceMenu.add(konecMI);
+		
+    //JMenu krivkaMenu = new JMenu("Křivka");
+    JMenu krivkaMenu = new JMenu("Curve");
+    menuBar.add(krivkaMenu);
+
+    //JMenuItem pridatBodyMI = new JMenuItem("Přidat body");
+    JMenuItem pridatBodyMI = new JMenuItem("Add control points");
+    krivkaMenu.add(pridatBodyMI);
+    pridatBodyMI.addActionListener(listener);
+		
+		
+    pridatBodyMI.setActionCommand(PRIDAT_AC);
+    JMenuItem smazatBodyMI = new JMenuItem(
+                                           //"Smazat body");
+                                           "Delete points");
+    krivkaMenu.add(smazatBodyMI);
+    smazatBodyMI.addActionListener(listener);
+		
+    smazatBodyMI.setActionCommand(SMAZAT_AC);
+		
+    //JMenuItem stupenMI=new JMenuItem("Zadat stupeň křivky");
+    JMenuItem stupenMI=new JMenuItem("Set curve degree");
+    krivkaMenu.add(stupenMI);
+    stupenMI.addActionListener(listener);
+    stupenMI.setActionCommand(STUPEN_AC);
+
+    //JMenu knotVecMenu = new JMenu("Vytvořit uzlový vektor");
+    JMenu knotVecMenu = new JMenu("Create knot vector");
+    krivkaMenu.add(knotVecMenu);
+
+    //JMenuItem clampedKVMI = new JMenuItem("Okrajový");
+    JMenuItem clampedKVMI = new JMenuItem("Clamped");
+    knotVecMenu.add(clampedKVMI);
+    clampedKVMI.setActionCommand(UZAVRENY_AC);
+    clampedKVMI.addActionListener(listener);
+    //JMenuItem unclampedKVMI = new JMenuItem("Uniformní");
+    JMenuItem unclampedKVMI = new JMenuItem("Uniform");
+    knotVecMenu.add(unclampedKVMI);
+    unclampedKVMI.setActionCommand(OTEVRENY_AC);
+    unclampedKVMI.addActionListener(listener);
+
+    //JMenuItem moveMI=new JMenuItem("Hýbat body");
+    JMenuItem moveMI=new JMenuItem("Move points");
+    krivkaMenu.add(moveMI);
+    moveMI.setActionCommand(MOVE_AC);
+    moveMI.addActionListener(listener);
+		
+    krivkaMenu.add(new JSeparator());
+
+    krivkaMenu.add(new JSeparator());
+
+    //JMenuItem novaMI=new JMenuItem("Nová křivka");
+    JMenuItem novaMI=new JMenuItem("New curve");
+    krivkaMenu.add(novaMI);
+    novaMI.setActionCommand(NOVA_AC);
+    novaMI.addActionListener(listener);
+		
+    //JMenuItem ulozitMI = new JMenuItem("Uložit křivku jako...");
+    JMenuItem ulozitMI = new JMenuItem("Save curve as...");
+    krivkaMenu.add(ulozitMI);
+    ulozitMI.setActionCommand(ULOZIT_AC);
+    ulozitMI.addActionListener(listener);
+    //JMenuItem nacistMI = new JMenuItem("Načíst křivku");
+    JMenuItem nacistMI = new JMenuItem("Load curve");
+    krivkaMenu.add(nacistMI);
+    nacistMI.setActionCommand(NACIST_AC);
+    nacistMI.addActionListener(listener);
+
+    c.gridy++;
+    JToolBar toolBar = new JToolBar();
+    getContentPane().add(toolBar, c);
+
+    ButtonGroup bg = new ButtonGroup();
+
+		
+    JButton novaB=new JButton();
+    //		novaB.setText("Nová");
+    //novaB.setToolTipText("Nová křivka");
+    novaB.setToolTipText("New curve");
+    novaB.setIcon(IconFactory.getIcon("demos/nurbs/icons/folder_new.png"));
+    novaB.setActionCommand(NOVA_AC);
+    novaB.addActionListener(listener);
+    toolBar.add(novaB);
+		
+    JButton ulozitB=new JButton();
+    ulozitB.setIcon(IconFactory.getIcon("demos/nurbs/icons/adept_sourceseditor.png"));
+    //		ulozitB.setText("Uložit");
+    //ulozitB.setToolTipText("Uložit");
+    ulozitB.setToolTipText("Save");
+    ulozitB.setActionCommand(ULOZIT_AC);
+    ulozitB.addActionListener(listener);
+    toolBar.add(ulozitB);
+		
+    JButton nahratB=new JButton();
+    //		nahratB.setText("Nahrát");
+    //nahratB.setToolTipText("Nahrát uloženou křivku");
+    nahratB.setToolTipText("Load curve");
+    nahratB.setIcon(IconFactory.getIcon("demos/nurbs/icons/fileimport.png"));
+    nahratB.setActionCommand(NACIST_AC);
+    nahratB.addActionListener(listener);
+    toolBar.add(nahratB);
+		
+    toolBar.add(new JToolBar.Separator());
+		
+    JToggleButton pridatTB = new JToggleButton();
+    //		pridatTB.setText("Přidat body");
+    //pridatTB.setToolTipText("Přidat body");
+    pridatTB.setToolTipText("Add points");
+    toolBar.add(pridatTB);
+    pridatTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/add.png"));
+    pridatTB.setActionCommand(PRIDAT_AC);
+    pridatTB.addActionListener(listener);
+    bg.add(pridatTB);
+    JToggleButton smazatTB = new JToggleButton();
+    //		smazatTB.setText("Smazat body");
+    //smazatTB.setToolTipText("Smazat body");
+    smazatTB.setToolTipText("Delete points");
+    toolBar.add(smazatTB);
+    smazatTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/fileclose.png"));
+    smazatTB.setActionCommand(SMAZAT_AC);
+    smazatTB.addActionListener(listener);
+    bg.add(smazatTB);
+		
+    JToggleButton stupenTB = new JToggleButton();
+    //		stupenTB.setText("Smazat body");
+    //stupenTB.setToolTipText("Zadat stupeň křivky");
+    stupenTB.setToolTipText("Set curve degree");
+    toolBar.add(stupenTB);
+    stupenTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/math_rsup.png"));
+    stupenTB.setActionCommand(STUPEN_AC);
+    stupenTB.addActionListener(listener);
+    bg.add(stupenTB);
+		
+
+    final JPopupMenu popup = new JPopupMenu();
+
+    //JMenuItem uzavrenyPopupMI = new JMenuItem("Okrajový");
+    JMenuItem uzavrenyPopupMI = new JMenuItem("Clamped");
+    popup.add(uzavrenyPopupMI);
+    uzavrenyPopupMI.setActionCommand(UZAVRENY_AC);
+    uzavrenyPopupMI.addActionListener(listener);
+    //JMenuItem otevrenyPopupMI = new JMenuItem("Uniformní");
+    JMenuItem otevrenyPopupMI = new JMenuItem("Uniform");
+    popup.add(otevrenyPopupMI);
+    otevrenyPopupMI.setActionCommand(OTEVRENY_AC);
+    otevrenyPopupMI.addActionListener(listener);
+
+    JToggleButton vytvoritButton = new JToggleButton();
+    //		vytvoritButton.setText("Vytvořit uzlový vektor");
+    //vytvoritButton.setToolTipText("Vytvořit uzlový vektor");
+    vytvoritButton.setToolTipText("Create knot vector");
+    vytvoritButton.setIcon(IconFactory.getIcon("demos/nurbs/icons/newfunction.png"));
+    bg.add(vytvoritButton);
+		
+    vytvoritButton.addMouseListener(new 
+                                    /**
+                                     * @author Tomáš Hráský
+                                     * Class connecting context menu to button on toolbar
+                                     * Třída pro připojení kontextového menu na tlačítko na liště nástrojů
+                                     */
+                                    MouseAdapter() {
+
+        @Override
+          public void mouseClicked(MouseEvent e) {
+          super.mouseClicked(e);
+          e.isPopupTrigger();
+          popup.show(e.getComponent(), e.getX(), e.getY());
+        }
+
+      });
+    popup.setInvoker(vytvoritButton);
+    toolBar.add(vytvoritButton);
+		
+    moveTB=new JToggleButton();
+    //		moveTB.setText("Hýbat body");
+    //moveTB.setToolTipText("Hýbat body");
+    moveTB.setToolTipText("Move points");
+    moveTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/mouse.png"));
+    toolBar.add(moveTB);
+    moveTB.setActionCommand(MOVE_AC);
+    moveTB.addActionListener(listener);
+    bg.add(moveTB);
+    toolBar.add(new JToolBar.Separator());
+    JButton infoB=new JButton();
+    //		infoB.setText("Ukončit");
+    //infoB.setToolTipText("O aplikaci");
+    infoB.setToolTipText("About");
+		
+    infoB.setIcon(IconFactory.getIcon("demos/nurbs/icons/info.png"));
+    toolBar.add(infoB);
+    infoB.setActionCommand(INFO_AC);
+    infoB.addActionListener(listener);
+    toolBar.add(new JToolBar.Separator());
+		
+    JButton exitB=new JButton();
+    //		exitB.setText("Ukončit");
+    //exitB.setToolTipText("Ukončit");
+    exitB.setToolTipText("Exit");
+		
+    exitB.setIcon(IconFactory.getIcon("demos/nurbs/icons/exit.png"));
+    toolBar.add(exitB);
+    exitB.setActionCommand(EXIT_AC);
+    exitB.addActionListener(listener);
+		
+    c.gridwidth = 1;
+
+    c.gridx = 0;
+    c.gridy = 2;
+
+    c.weightx = 1;
+    c.weighty = 1;
+
+    getContentPane().add(glCanvas, c);
+    c.gridx = 1;
+    JPanel rightPanel = new JPanel(new GridBagLayout());
+    GridBagConstraints cc = new GridBagConstraints();
+    cc.insets = new Insets(5, 5, 5, 5);
+    xSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, 1));
+    ySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, 1));
+    wSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, .05));
+
+    SpinnerListener spinnerListener = new SpinnerListener(this);
+    xSpinner.addChangeListener(spinnerListener);
+    xSpinner.setName(X_SPINNER_NAME);
+    ySpinner.addChangeListener(spinnerListener);
+    ySpinner.setName(Y_SPINNER_NAME);
+    wSpinner.addChangeListener(spinnerListener);
+    wSpinner.setName(W_SPINNER_NAME);
+
+    cc.gridx = 0;
+    cc.gridy = 0;
+
+    cc.gridwidth = 2;
+    cc.weighty = 1;
+    rightPanel.add(new JPanel(), cc);
+    cc.weighty = 0;
+    cc.gridwidth = 1;
+
+    cc.gridy++;
+    rightPanel.add(new JLabel("X"), cc);
+    cc.gridy++;
+    rightPanel.add(new JLabel("Y"), cc);
+    cc.gridy++;
+    rightPanel.add(new JLabel("W"), cc);
+
+    cc.gridx = 1;
+    cc.gridy = 1;
+    rightPanel.add(xSpinner, cc);
+    cc.gridy++;
+    rightPanel.add(ySpinner, cc);
+    cc.gridy++;
+    rightPanel.add(wSpinner, cc);
+
+    xSpinner.setEnabled(false);
+    ySpinner.setEnabled(false);
+    wSpinner.setEnabled(false);
+
+    c.weightx = 0;
+    c.weighty = 0;
+    getContentPane().add(rightPanel, c);
+
+    c.gridx = 0;
+    c.gridy++;
+
+    knotSlider = new JKnotSlider(Curve.getInstance().getKnots());
+    knotSlider.addActionListener(this);
+    getContentPane().add(knotSlider, c);
+
+    pack();
+    invalidate();
+    setVisible(true);
+  }
+
+  /**
+   * Main method starting application
+   * Metoda pro spuštění aplikace
+   * @param args no arguments accepted 
+   * 
+   */
+  public static void main(String[] args) {
+    new CurveApp();
+
+  }
+
+  /**
+   * Reaction to request for redrive OpenGL canvas - repaints canvas, sets actually selected control points coords to editing components
+   * Reakce na požadavek překreslení OpenGL plátna, překreslí plátno a nastaví souřadnice aktuálního vybraného bodu do editačních komponent
+   */
+  public void updateGLCanvas() {
+    glCanvas.repaint();
+    if (Curve.getInstance().getBodIndex() >= 0) {
+      xSpinner.setEnabled(true);
+      ySpinner.setEnabled(true);
+      wSpinner.setEnabled(true);
+
+      xSpinner.setValue(Double.valueOf(Math.round(Curve.getInstance()
+                                                  .getActiveX())));
+      ySpinner.setValue(Double.valueOf(Math.round(Curve.getInstance()
+                                                  .getActiveY())));
+      wSpinner.setValue(Double.valueOf(Curve.getInstance().getActiveW()));
+    } else {
+      xSpinner.setEnabled(false);
+      ySpinner.setEnabled(false);
+      wSpinner.setEnabled(false);
+    }
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+   */
+  public void actionPerformed(ActionEvent e) {
+    JKnotSlider src = (JKnotSlider) e.getSource();
+    if(src.checkKnotMulti(Curve.getInstance().getOrder())){
+      Curve.getInstance().setKnots(src.getKnotsFloat());
+    }else{
+      //JOptionPane.showMessageDialog(this,"Překročení maximální násobnosti uzlu","Chyba",JOptionPane.ERROR_MESSAGE);
+      JOptionPane.showMessageDialog(this,"Maximum knot multiplicity exceeded","Error",JOptionPane.ERROR_MESSAGE);
+      src.setKnots(Curve.getInstance().getKnots());
+    }
+    updateGLCanvas();
+  }
+
+  /**
+   * Returns OpenGL canvas
+   * Vrací OpenGL plátno
+   * @return OpenGL canvas
+   */
+  public GLCanvas getGlCanvas() {
+    return glCanvas;
+  }
+
+  /**
+   * Returns mouse events listener
+   * Vrací listener událostí myši
+   * @return mouse listener
+   */
+  public CurveMouseListener getMouseListener() {
+    return mouseListener;
+  }
+
+  /**
+   * Creates NURBS curve with clamped knot vector
+   * Vytvoří NURBS křivku s okrajovým uzlovým vektorem
+   */
+  public void uzavernyKV() {
+    int stupen = Curve.getInstance().getOrder();
+    int pocetBodu = Curve.getInstance().getCtrlPoints().length / 4;
+    if (stupen <= pocetBodu) {
+      int knotCount = stupen + pocetBodu;
+      int middlePartSize = knotCount - 2 * stupen;
+      float[] newKnots = new float[knotCount];
+      int i;
+      int j = 0;
+      float middleStep = 1f / (middlePartSize + 2);
+      float knot = middleStep;
+
+      // knot=.5f;
+
+      for (i = 0; i < stupen; i++)
+        newKnots[j++] = 0;
+      for (i = 0; i < middlePartSize; i++) {
+        newKnots[j++] = knot;
+        knot += middleStep;
+      }
+      for (i = 0; i < stupen; i++)
+        newKnots[j++] = 1;
+
+      postNewKnot(newKnots);
+
+    } else
+      //errorMessage("Malý počet řídících bodů vzhledem k zadanému stupni křivky");
+      errorMessage("Too few control points regarding set curve degree");
+  }
+
+  /**
+   * Displays modal window with error report
+   * Zobrazí modální okno s hlášením chyby
+   * @param error error message
+   */
+  public void errorMessage(String error){
+    //JOptionPane.showMessageDialog(this,error,"Chyba!",JOptionPane.ERROR_MESSAGE);
+    JOptionPane.showMessageDialog(this,error,"Error!",JOptionPane.ERROR_MESSAGE);
+  }
+	
+  /**
+   * Creates NURBS curves with uniform knot vector
+   * Vytvoří NURBS křivku s uniformním uzlovým vektorem
+   */
+  public void otevrenyKV() {
+    int stupen = Curve.getInstance().getOrder();
+    int pocetBodu = Curve.getInstance().getCtrlPoints().length / 4;
+    if (stupen <= pocetBodu) {
+      int knotCount = stupen + pocetBodu;
+      int middlePartSize = knotCount;
+      float[] newKnots = new float[knotCount];
+      int i;
+      int j = 0;
+      float middleStep = 1f / (middlePartSize - 1);
+      float knot = 0;
+
+      // knot=.5f;
+
+      // for(i=0;i<stupen;i++)
+      // newKnots[j++]=0;
+      for (i = 0; i < middlePartSize; i++) {
+        newKnots[j++] = knot;
+        knot += middleStep;
+      }
+      // for(i=0;i<stupen;i++)
+      // newKnots[j++]=1;
+
+      postNewKnot(newKnots);
+    }
+    else
+      //errorMessage("Malý počet řídících bodů vzhledem k zadanému stupni křivky");
+      errorMessage("Too few control points regarding set curve degree");
+  }
+
+  /**
+   * Method called after adding new knot
+   * Metoda volaná po přidání nového uzlu
+   * @param newKnots new knot vector
+   */
+  private void postNewKnot(float[] newKnots) {
+    Curve.getInstance().setKnots(newKnots);
+    knotSlider.setKnots(newKnots);
+    Curve.getInstance().setIsCurveFinished(true);
+    updateGLCanvas();
+    moveTB.setSelected(true);
+  }
+
+  /**
+   * Activates MOVE MODE button
+   * Aktivuje tlačítko módu pohybu řícími body
+   */
+  public void selectMoveButt() {
+    moveTB.setSelected(true);
+  }
+
+  /**
+   * Sets data source for knot editing component from knot vector of curve object
+   * Nastaví zdroj dat komponenty pro editaci uzlového vektoru podle uz. vektoru v objektu křivky
+   */
+  public void updateJKnotSlider() {
+    knotSlider.setKnots(Curve.getInstance().getKnots());
+  }
+}
diff --git a/src/demos/nurbs/curveapp/CurveMouseListener.java b/src/demos/nurbs/curveapp/CurveMouseListener.java
new file mode 100755
index 0000000..b74e1cf
--- /dev/null
+++ b/src/demos/nurbs/curveapp/CurveMouseListener.java
@@ -0,0 +1,180 @@
+package demos.nurbs.curveapp;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * Class reacting to mouse events (implements interface for button press, drag and movement)
+ * Třída zpracovávající události myši (implementuje rozhraní zpracovávající stisk tlačítek i pohyb a tažení myší)
+ * @author Tomáš Hráský
+ *
+ */
+public class CurveMouseListener implements MouseListener, MouseMotionListener {
+  /**
+   * Actually selected control point index
+   * Index aktuálně vybraného řídícího bodu
+   */
+  private int bodIndex;
+
+  /**
+   * Window listener is connected to
+   * Okno k nemuž listener patří
+   */
+  private CurveApp appWindow;
+
+  /**
+   * Action type
+   * Typ prováděné činnosti
+   */
+  private String actionType;
+
+  /**
+   * Pixel tolerance when selecting control point by clicking
+   * Tolerance pro indikaci kliku na řídící bod
+   */
+  private static final int TOLERANCE=10;
+
+  /**
+   * Creates new listener with connection to given app window
+   * Vytvoří listener s odkazem na zadané okno
+   * @param app rodičovské okno
+   */
+  public CurveMouseListener(CurveApp app) {
+    this.appWindow=app;
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
+   */
+  public void mouseClicked(MouseEvent e) {
+    if(actionType==CurveApp.PRIDAT_AC){
+      Curve.getInstance().setIsCurveFinished(false);
+      float x=e.getX();
+      float y=e.getY();
+      float z=0;
+      float w=1;
+      int size;
+      float[] newCtrls;
+      try{
+        size=Curve.getInstance().getCtrlPoints().length;
+      }catch (Exception ex) {
+        size=0;
+      }
+      newCtrls=new float[size+4];
+      System.arraycopy(Curve.getInstance().getCtrlPoints(),0,newCtrls,0,size);
+			
+      newCtrls[size]=x;
+      newCtrls[size+1]=y;
+      newCtrls[size+2]=z;
+      newCtrls[size+3]=w;
+      Curve.getInstance().setCtrlPoints(newCtrls);
+    }else if(actionType==CurveApp.SMAZAT_AC&&bodIndex>=0){
+      Curve.getInstance().setIsCurveFinished(false);
+      int size=Curve.getInstance().getCtrlPoints().length;
+      float[] newCtrls=new float[size-4];
+			
+      int firstPartSize=(bodIndex)*4;
+      int secondPartSize=newCtrls.length-firstPartSize;
+      System.arraycopy(Curve.getInstance().getCtrlPoints(),0,newCtrls,0,firstPartSize);
+      System.arraycopy(Curve.getInstance().getCtrlPoints(),firstPartSize+4,newCtrls,firstPartSize,secondPartSize);
+      bodIndex=-1;
+      Curve.getInstance().setBodIndex(bodIndex);
+      Curve.getInstance().setCtrlPoints(newCtrls);
+    }
+    appWindow.updateGLCanvas();
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
+   */
+  public void mousePressed(MouseEvent e) {
+    //		if(actionType==MOVE_AC){
+    float[] ctrlpoints=Curve.getInstance().getCtrlPoints();
+    int x=e.getX();
+    int y=e.getY();
+    this.bodIndex=-1;
+    //			System.out.println(ctrlpoints.length);
+    for(int i=0;i<ctrlpoints.length/4;i++){
+      float xS = ctrlpoints[i*4]/ctrlpoints[i*4+3];
+      float yS = ctrlpoints[i*4+1]/ctrlpoints[i*4+3];
+      if(x>=xS-TOLERANCE&&x<=xS+TOLERANCE&&y>=yS-TOLERANCE&&y<=yS+TOLERANCE){
+        this.bodIndex=i;
+      }                    
+    }
+			
+    Curve.getInstance().setBodIndex(bodIndex);
+    //		}
+    appWindow.updateGLCanvas();
+		
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
+   */
+  public void mouseReleased(MouseEvent e) {
+    //		this.bodIndex=-1;
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
+   */
+  public void mouseEntered(MouseEvent e) {
+
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
+   */
+  public void mouseExited(MouseEvent e) {
+
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
+   */
+  public void mouseDragged(MouseEvent e) {
+    if(this.bodIndex>=0){
+      int x=e.getX();
+      int y=e.getY();
+			
+      Curve.getInstance().setActiveX(x);
+      Curve.getInstance().setActiveY(y);
+    }
+    appWindow.updateGLCanvas();
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
+   */
+  public void mouseMoved(MouseEvent e) {
+		
+  }
+
+  /**
+   * Set action type
+   * Nastaví typ prováděné činnosti
+   * @param action Action type
+   */
+  public void setActionType(String action) {
+    this.actionType=action;
+  }
+
+  /**
+   * Returns actually selected control point index
+   * Vrací index aktuálně vybraného řídícího bodu
+   * @return actually selected control point index
+   */
+  public int getBodIndex() {
+    return bodIndex;
+  }
+
+  /**
+   * Sets actually selected control point index
+   * Nastavuje index aktuálně vybraného řídícího bodu
+   * @param bodIndex actually selected control point index
+   */
+  public void setBodIndex(int bodIndex) {
+    this.bodIndex = bodIndex;
+  }
+}
diff --git a/src/demos/nurbs/curveapp/GLListener.java b/src/demos/nurbs/curveapp/GLListener.java
new file mode 100755
index 0000000..18bf36f
--- /dev/null
+++ b/src/demos/nurbs/curveapp/GLListener.java
@@ -0,0 +1,141 @@
+package demos.nurbs.curveapp;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.glu.*;
+
+import com.sun.opengl.util.GLUT;
+
+/**
+ * Listener raacting to OpenGL canvas events
+ * Listener reagující na události na OpenGL plátně
+ * @author Tomáš Hráský
+ *
+ */
+public class GLListener implements GLEventListener {
+
+  /**
+   * OpenGL object
+   * objekt realizující základní OpenGL funkce
+   */
+  private GL gl;
+
+  /**
+   * GLU
+   * Objekt realizující funkce nadstavbové knihovny GLU
+   */
+  private GLU glu;
+
+  /**
+   * GLUT object
+   * Objekt realizující funkce nadstavbové knihovny GLUT
+   */
+  private GLUT glut;
+	
+  /**
+   * NURBS curve object
+   * OpenGL Objekt NURBS křivky
+   */
+  private GLUnurbs nurbs;
+
+	
+  /* (non-Javadoc)
+   * @see javax.media.opengl.GLEventListener#init(javax.media.opengl.GLAutoDrawable)
+   */
+  public void init(GLAutoDrawable drawable) {
+    this.gl = drawable.getGL();
+    this.glu = new GLU();
+    this.glut=new GLUT();
+
+    this.nurbs = glu.gluNewNurbsRenderer();
+    gl.glClearColor(1, 1, 1, 1);
+  }
+
+  /* (non-Javadoc)
+   * @see javax.media.opengl.GLEventListener#display(javax.media.opengl.GLAutoDrawable)
+   */
+  public void display(GLAutoDrawable drawable) {
+
+    gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+
+    gl.glMatrixMode(GL.GL_MODELVIEW);
+    gl.glLoadIdentity();
+
+    float[] knots = Curve.getInstance().getKnots();
+    float[] ctrlpoints = Curve.getInstance().getCtrlPoints();
+		
+    gl.glEnable(GL.GL_LINE_SMOOTH);
+    gl.glEnable(GL.GL_BLEND);
+    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
+    gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_DONT_CARE);
+	    
+    gl.glLineWidth(3);
+		
+    if(Curve.getInstance().isCurveFinished()){
+      glu.gluBeginCurve(nurbs);
+      glu.gluNurbsCurve(nurbs, knots.length, knots, 4, ctrlpoints, Curve.getInstance().getOrder(), GL.GL_MAP1_VERTEX_4);
+      glu.gluEndCurve(nurbs);
+    }
+		
+    gl.glColor3f(0,0,0);
+    gl.glPointSize(5);
+    gl.glBegin(GL.GL_POINTS);
+    for (int i = 0; i < ctrlpoints.length / 4; i++) {
+      //			if(i!=Curve.getInstance().getBodIndex())
+      gl.glVertex3d(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3],
+                    ctrlpoints[i * 4 + 2]/ctrlpoints[i * 4 + 3]);
+    }
+    gl.glEnd();
+		
+		
+    for (int i = 0; i < ctrlpoints.length / 4; i++) {
+      //			if(i!=Curve.getInstance().getBodIndex())
+      //			gl.glPushMatrix();
+      gl.glRasterPos2f(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3]-5);
+      glut.glutBitmapString(GLUT.BITMAP_HELVETICA_18,String.valueOf(i+1));
+      //			gl.glPopMatrix();
+    }
+		
+		
+    gl.glLineWidth(1);
+    gl.glBegin(GL.GL_LINE_STRIP);
+    for (int i = 0; i < ctrlpoints.length / 4; i++) {
+      //			if(i!=Curve.getInstance().getBodIndex())
+      gl.glVertex3d(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3],
+                    ctrlpoints[i * 4 + 2]/ctrlpoints[i * 4 + 3]);
+    }
+    gl.glEnd();
+    gl.glColor3f(0,0,1);
+    if(Curve.getInstance().getBodIndex()>=0){
+      gl.glPointSize(8);
+      gl.glBegin(GL.GL_POINTS);
+      int i=Curve.getInstance().getBodIndex();
+      gl.glVertex3d(ctrlpoints[i * 4]/ctrlpoints[i * 4 + 3], ctrlpoints[i * 4 + 1]/ctrlpoints[i * 4 + 3],
+                    ctrlpoints[i * 4 + 2]/ctrlpoints[i * 4 + 3]);
+      gl.glEnd();
+    }
+			
+		
+
+  }
+
+  /* (non-Javadoc)
+   * @see javax.media.opengl.GLEventListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int)
+   */
+  public void reshape(GLAutoDrawable drawable, int x, int y, int width,
+                      int height) {
+    gl.glMatrixMode(GL.GL_PROJECTION);
+    gl.glLoadIdentity();
+    gl.glOrtho(0, drawable.getWidth(), 0, drawable.getHeight(), -1, 1);
+    gl.glScalef(1, -1, 1);
+    gl.glTranslatef(0, -drawable.getHeight(), 0);
+
+  }
+
+  /* (non-Javadoc)
+   * @see javax.media.opengl.GLEventListener#displayChanged(javax.media.opengl.GLAutoDrawable, boolean, boolean)
+   */
+  public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {
+  }
+}
diff --git a/src/demos/nurbs/curveapp/MyFloat.java b/src/demos/nurbs/curveapp/MyFloat.java
new file mode 100755
index 0000000..6adc2ef
--- /dev/null
+++ b/src/demos/nurbs/curveapp/MyFloat.java
@@ -0,0 +1,55 @@
+package demos.nurbs.curveapp;
+
+import simple.xml.Attribute;
+import simple.xml.Root;
+
+/**
+ * Class for serializing decimal point number using SimpleXML
+ * Třída umožňující serializaci desetinného čísla ve formátu plovoucí čárky (float)
+ * @author Tomáš Hráský
+ *
+ */
+@Root(name="floatval")
+public class MyFloat {
+  /**
+   * Value
+   * Hodnota
+   */
+  @Attribute(name="val")
+    private float value;
+
+  /**
+   * Constructor, sets value to 0
+   * Konstrktor, hodnota je defaultně 0 
+   */
+  public MyFloat(){
+    value=0;
+  }
+	
+  /**
+   * Creates instance with specified value
+   * Vytvoří instanci objektu s požadovanou hodnotou
+   * @param f value
+   */
+  public MyFloat(float f) {
+    value = f;
+  }
+
+  /**
+   * Returns value of decimal number
+   * Vrací hodnotu des. čísla
+   * @return value
+   */
+  public float getValue() {
+    return value;
+  }
+
+  /**
+   * Sets value
+   * Nastavuje hodnotu objektu
+   * @param value value
+   */
+  public void setValue(float value) {
+    this.value = value;
+  }
+}
diff --git a/src/demos/nurbs/curveapp/SpinnerListener.java b/src/demos/nurbs/curveapp/SpinnerListener.java
new file mode 100755
index 0000000..ccc5ac4
--- /dev/null
+++ b/src/demos/nurbs/curveapp/SpinnerListener.java
@@ -0,0 +1,47 @@
+package demos.nurbs.curveapp;
+
+import javax.swing.JSpinner;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/**
+ * Listener reacting to events on GUI components setting coords and weight of selected control point
+ * Listener zpracovávající události na komponentách editujících souřadnice a váhu vybraného řídícícho bodu
+ * @author Tomáš Hráský
+ *
+ */
+public class SpinnerListener implements ChangeListener {
+
+  /**
+   * Application window 
+   * Okno aplikace, k němuž listener patří
+   */
+  private CurveApp appWindow;
+
+  /**
+   * Creates new instance with link to parent window
+   * Vytvoří instanci objektu s odkazem na rodičovské okno
+   * @param app app window
+   */
+  public SpinnerListener(CurveApp app) {
+    this.appWindow=app;
+  }
+
+  /* (non-Javadoc)
+   * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
+   */
+  public void stateChanged(ChangeEvent e) {
+    JSpinner src=(JSpinner) e.getSource();
+    float val = 0;
+    if(src.getValue() instanceof Double) val=((Double) src.getValue()).floatValue();
+    if(src.getValue() instanceof Float) val=((Float) src.getValue()).floatValue();
+		
+    if(src.getName()==CurveApp.X_SPINNER_NAME)
+      Curve.getInstance().setActiveX(val);
+    if(src.getName()==CurveApp.Y_SPINNER_NAME)
+      Curve.getInstance().setActiveY(val);
+    if(src.getName()==CurveApp.W_SPINNER_NAME)
+      Curve.getInstance().setActiveW(val);
+    appWindow.updateGLCanvas();
+  }
+}
-- 
cgit v1.2.3