[ Cal Lightman @ 18.11.2013. 15:15 ] @
Pozdrav svima.

Pri kraju sam sa projektom koji radim za svoje potrebe, u pitanju je simple phone book. Uploadovao sam ceo solution ovde, pa ko ima malo vremena može da se iscima da pogleda.

Interfejs izgleda ovako, a evo i problema ujedno:



Naizgled sve radi lepo, međutim, verujem da je problem nastao kada sam podesio:

Code:
listView1.Sorting = SortOrder.Ascending;

Neko možda uviđa u čemu je stvar. Dakle:

1) Ako uzmemo za primer da su u listi 6 kontakta, a da Kontakt 1 živi u gradu 1, ulici 1, sa brojem telefona 1...a Kontakt 2 živi u gradu 2, ulici 2... [niz se nastavlja] - i, na primer, želim da editujem Kontakt 4 tako da postane Kontakt 7 - jednostavno se podaci pomešaju, ne znam po kom obrascu. Dakle prvobitni Kontakt 4 (koji je trebalo da postane Kontakt 7) je postao Kontakt 6 ... i tako dalje - sve ispremeštano.

Čini se da je u pitanju Save button (toolStripButton1_Click), nisam pametan.

2) Ako uzmemo za primer da su u listi 6 kontakta, i hoću da obrišem svih 6 - izbrisaće njih petoro, a jedan će ostati. Isto tako, ako ih je 100 - obrisaće 99, a ostaće 1.

Čini se da je u pitanju Remove metoda.

Evo i koda:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using System;
using System.Xml.Xsl;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        List<Person> people = new List<Person>();
        private void Form1_Load(object sender, EventArgs e)
        {
            toolStripButton5.Enabled = false;
            listView1.Sorting = SortOrder.Ascending;
            string path = "E:\\Cloud\\GDrive\\Backup\\System Files\\Phone Book\\Contacts.xml";
            if (!File.Exists(path))
            {
                XmlTextWriter xW = new XmlTextWriter(path, Encoding.UTF8);
                xW.WriteStartElement("People");
                xW.WriteEndElement();
                xW.Close();
            }
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(path);
            foreach (XmlNode xNode in xDoc.SelectNodes("People/Person"))
            {
                Person p = new Person();
                p.Name = xNode.SelectSingleNode("Name").InnerText;
                p.Hometown = xNode.SelectSingleNode("Hometown").InnerText;
                p.Address = xNode.SelectSingleNode("Address").InnerText;
                p.Birthday = DateTime.FromFileTime(Convert.ToInt64(xNode.SelectSingleNode("Birthday").InnerText));
                p.Phone = xNode.SelectSingleNode("Phone").InnerText;
                p.Email = xNode.SelectSingleNode("Email").InnerText;
                p.AdditionalInfo = xNode.SelectSingleNode("AdditionalInfo").InnerText;
                people.Add(p);
                listView1.Items.Add(p.Name);
                UserCount();
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {

        }
        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count == 0) return;
            textBox1.Text = people[listView1.SelectedItems[0].Index].Name;
            textBox2.Text = people[listView1.SelectedItems[0].Index].Hometown;
            textBox3.Text = people[listView1.SelectedItems[0].Index].Address;
            textBox4.Text = people[listView1.SelectedItems[0].Index].Phone;
            textBox5.Text = people[listView1.SelectedItems[0].Index].Email;
            textBox6.Text = people[listView1.SelectedItems[0].Index].AdditionalInfo;
            dateTimePicker1.Value = people[listView1.SelectedItems[0].Index].Birthday;
            textBox1.ReadOnly = true;
            textBox2.ReadOnly = true;
            textBox3.ReadOnly = true;
            textBox4.ReadOnly = true;
            textBox5.ReadOnly = true;
            textBox6.ReadOnly = true;
            dateTimePicker1.Enabled = false;
            toolStripButton5.Enabled = true;
        }

        private void button3_Click(object sender, EventArgs e)
        {

        }
        void Remove()
        {
            try
            {
                if (listView1.SelectedItems.Count > 0)
                {
                    people.RemoveAt(listView1.SelectedItems[0].Index);
                    listView1.SelectedItems[0].Remove();
                    textBox1.Text = "";
                    textBox2.Text = "";
                    textBox3.Text = "";
                    textBox4.Text = "";
                    textBox5.Text = "";
                    textBox6.Text = "";
                    dateTimePicker1.Value = DateTime.Now;
                    if (listView1.SelectedItems.Count == 0)
                    {
                        textBox1.ReadOnly = false;
                        textBox2.ReadOnly = false;
                        textBox3.ReadOnly = false;
                        textBox4.ReadOnly = false;
                        textBox5.ReadOnly = false;
                        textBox6.ReadOnly = false;
                        dateTimePicker1.Enabled = true;
                    }
                }
                else
                {
                    MessageBox.Show("Nothing is selected! ", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch { }
        }
        void UserCount()
        {
            try
            {
                if ((listView1.Items.Count) == 1)
                {
                    toolStripLabel1.Text = "Total: " + Convert.ToString(listView1.Items.Count) + "& contact";
                }
                else
                {
                    toolStripLabel1.Text = "Total: " + Convert.ToString(listView1.Items.Count) + "& contacts";
                }
            }
            catch { }
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            XmlDocument xDoc = new XmlDocument();
            string path = "E:\\Cloud\\GDrive\\Backup\\System Files\\Phone Book\\Contacts.xml";
            xDoc.Load(path);
            XmlNode xNode = xDoc.SelectSingleNode("People");
            xNode.RemoveAll();
            foreach (Person p in people)
            {
                XmlNode xTop = xDoc.CreateElement("Person");
                XmlNode xName = xDoc.CreateElement("Name");
                XmlNode xHometown = xDoc.CreateElement("Hometown");
                XmlNode xAddress = xDoc.CreateElement("Address");
                XmlNode xBirthday = xDoc.CreateElement("Birthday");
                XmlNode xPhone = xDoc.CreateElement("Phone");
                XmlNode xEmail = xDoc.CreateElement("Email");
                XmlNode xAdditionalInfo = xDoc.CreateElement("AdditionalInfo");
                xName.InnerText = p.Name;
                xHometown.InnerText = p.Hometown;
                xAddress.InnerText = p.Address;
                xBirthday.InnerText = p.Birthday.ToFileTime().ToString();
                xPhone.InnerText = p.Phone;
                xEmail.InnerText = p.Email;
                xAdditionalInfo.InnerText = p.AdditionalInfo;
                xTop.AppendChild(xName);
                xTop.AppendChild(xHometown);
                xTop.AppendChild(xAddress);
                xTop.AppendChild(xBirthday);
                xTop.AppendChild(xPhone);
                xTop.AppendChild(xEmail);
                xTop.AppendChild(xAdditionalInfo);
                xDoc.DocumentElement.AppendChild(xTop);
                xDoc.Save(path);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {

        }

        private void button5_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Remove();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count > 0)
            {
                people[listView1.SelectedItems[0].Index].Name = textBox1.Text;
                people[listView1.SelectedItems[0].Index].Hometown = textBox2.Text;
                people[listView1.SelectedItems[0].Index].Address = textBox3.Text;
                people[listView1.SelectedItems[0].Index].Phone = textBox4.Text;
                people[listView1.SelectedItems[0].Index].Email = textBox5.Text;
                people[listView1.SelectedItems[0].Index].Birthday = dateTimePicker1.Value;
                people[listView1.SelectedItems[0].Index].AdditionalInfo = textBox6.Text;
                listView1.SelectedItems[0].Text = textBox1.Text;
                textBox1.ReadOnly = true;
                textBox2.ReadOnly = true;
                textBox3.ReadOnly = true;
                textBox4.ReadOnly = true;
                textBox5.ReadOnly = true;
                textBox6.ReadOnly = true;
                dateTimePicker1.Enabled = false;
            }
            else
            {
                MessageBox.Show("Nothing is selected ", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            UserCount();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count > 0)
            {
                MessageBox.Show("Please make sure you have no contacts selected!", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else if (textBox1.ReadOnly == true) { MessageBox.Show("Please make sure you refresh fields first!", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information); }
            else
            {
                if ((textBox1.Text.Trim().Length == 0)) { MessageBox.Show("Please enter contact's name!", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information); }
                else
                {
                    Person p = new Person();
                    p.Name = textBox1.Text;
                    p.Hometown = textBox2.Text;
                    p.Address = textBox3.Text;
                    p.Phone = textBox4.Text;
                    p.Email = textBox5.Text;
                    p.Birthday = dateTimePicker1.Value;
                    p.AdditionalInfo = textBox6.Text;
                    people.Add(p);
                    listView1.Items.Add(p.Name);
                    textBox1.Text = "";
                    textBox2.Text = "";
                    textBox3.Text = "";
                    textBox4.Text = "";
                    textBox5.Text = "";
                    textBox6.Text = "";
                    dateTimePicker1.Value = DateTime.Now;
                    UserCount();
                }
            }
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            Remove();
            UserCount();
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count == 0)
            {
                UserCount();
                textBox1.Text = "";
                textBox2.Text = "";
                textBox3.Text = "";
                textBox4.Text = "";
                textBox5.Text = "";
                textBox6.Text = "";
                dateTimePicker1.Value = DateTime.Now;
                textBox1.ReadOnly = false;
                textBox2.ReadOnly = false;
                textBox3.ReadOnly = false;
                textBox4.ReadOnly = false;
                textBox5.ReadOnly = false;
                textBox6.ReadOnly = false;
                dateTimePicker1.Enabled = true;
                toolStripButton5.Enabled = false;
            }
        }

        private void toolStripLabel1_Click(object sender, EventArgs e)
        {

        }

        private void toolStripLabel1_Click_1(object sender, EventArgs e)
        {

        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count > 0)
            {
                textBox1.ReadOnly = false;
                textBox2.ReadOnly = false;
                textBox3.ReadOnly = false;
                textBox4.ReadOnly = false;
                textBox5.ReadOnly = false;
                textBox6.ReadOnly = false;
                dateTimePicker1.Enabled = true;
            }
            else
            {
                MessageBox.Show("Nothing is selected! ", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
                toolStripButton5.Enabled = false;
                textBox1.ReadOnly = true;
                textBox2.ReadOnly = true;
                textBox3.ReadOnly = true;
                textBox4.ReadOnly = true;
                textBox5.ReadOnly = true;
                textBox6.ReadOnly = true;
                dateTimePicker1.Enabled = false;
            }
        }
    }
    class Person
    {
        public string Name
        {
            get;
            set;
        }
        public string Hometown
        {
            get;
            set;
        }
        public string Email
        {
            get;
            set;
        }
        public string Address
        {
            get;
            set;
        }
        public string Phone
        {
            get;
            set;
        }
        public string AdditionalInfo
        {
            get;
            set;
        }
        public DateTime Birthday
        {
            get;
            set;
        }
    }
}


Da li neko ima rešenje? Please, help.


[Ovu poruku je menjao Cal Lightman dana 18.11.2013. u 17:51 GMT+1]
[ Mihajlo Cvetanović @ 18.11.2013. 16:32 ] @
1) Nema svrhe što si ubacio sortiranje liste kad u listView1_SelectedIndexChanged i dalje koristiš indeks selektovanog elementa da bi znao koji je element u pitanju. Moraš umesto indeksa da koristiš vrednost elementa.

2) Možda je isti problem sa indeksom i u ovom problemu, samo se ogleda drugačije. U funkciji Remove takođe koristiš indeks, a treba da pronađeš element po vrednosti.
[ Cal Lightman @ 18.11.2013. 16:44 ] @
Au, totalno mi je je jasno u čemu je stvar! Verovatno si u pravu da je kod drugog problema ista stvar u pitanju.

S tim da je ovo moj prvi projekat i većinu stvari sam radio gledajući sa strane razne tutoriale, tako da ne znam kako da to ispravim. Prvo mi je ovako laički palo na pamet da umesto .Index prepravim u .Value ali malo sutra.

Ako je neko voljan da pomogne, bio bih mu vrlo zahvalan.

Anyway, hvala Mihajlo!

[ Mihajlo Cvetanović @ 19.11.2013. 10:05 ] @
Svuda u kodu zameni people[listView1.SelectedItems[0].Index] sa person, gde je person

Code:
Person person = FindPerson(listView1.SelectedItems[0].Text);


gde je FindPerson

Code:
private Person FindPerson(string name)
{
    return people.Find(x => x.Name == name);
}
[ Cal Lightman @ 19.11.2013. 17:27 ] @
Mihajlo, nisam te baš najbolje shvatio, molim te nemoj zameriti.

1)

FIND: people[listView1.SelectedItems[0].Index]
REPLACE: person

To sam obavio.

2)

Dodao:

Code:
Person person = FindPerson(listView1.SelectedItems[0].Text);


3)

Dodao:

Code:
private Person FindPerson(string name)
{
    return people.Find(x => x.Name == name);
}


Jesmo se dobro razumeli?

If so:



Svakako, hvala na pomoći!
[ Mihajlo Cvetanović @ 20.11.2013. 09:25 ] @
Mislio sam da "Person person = ..." dodaš u svakoj funkciji gde je to potrebno, na onom mestu gde je to logično. Obično na početku funkcije. Poent je bila da se Kod unutar FindPerson funkcije izvršava samo jednom, a ne za svaki property klase Person. Hteo sam da izbegnem ovakav izuzetno neefikasan kod:

Code:
                FindPerson(listView1.SelectedItems[0].Text).Name = textBox1.Text;
                FindPerson(listView1.SelectedItems[0].Text).Hometown = textBox2.Text;
                FindPerson(listView1.SelectedItems[0].Text).Address = textBox3.Text;
                FindPerson(listView1.SelectedItems[0].Text).Phone = textBox4.Text;
                FindPerson(listView1.SelectedItems[0].Text).Email = textBox5.Text;
                FindPerson(listView1.SelectedItems[0].Text).Birthday = dateTimePicker1.Value;
                FindPerson(listView1.SelectedItems[0].Text).AdditionalInfo = textBox6.Text;
                listView1.SelectedItems[0].Text = textBox1.Text;


I da umesto toga stoji ovo:

Code:
                Person person = FindPerson(listView1.SelectedItems[0].Text);
                person.Name = textBox1.Text;
                person.Hometown = textBox2.Text;
                person.Address = textBox3.Text;
                person.Phone = textBox4.Text;
                person.Email = textBox5.Text;
                person.Birthday = dateTimePicker1.Value;
                person.AdditionalInfo = textBox6.Text;
                listView1.SelectedItems[0].Text = textBox1.Text;


[ Cal Lightman @ 20.11.2013. 13:34 ] @
Mislim da sam te sad lepo razumeo.

Anyway, prvo sam dodao:

Code:
private Person FindPerson(string name)
{
    return people.Find(x => x.Name == name);
}

... pa sam svuda gde se spominje (po 7 puta u 2 funkcije)

Code:
people[listView1.SelectedItems[0].Index]

zamenio sa person:


Funkcija 1:

Code:
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            Person person = FindPerson(listView1.SelectedItems[0].Text);
            if (listView1.SelectedItems.Count == 0) return;
            textBox1.Text = person.Name;
            textBox2.Text = person.Hometown;
            textBox3.Text = person.Address;
            textBox4.Text = person.Phone;
            textBox5.Text = person.Email;
            textBox6.Text = person.AdditionalInfo;
            dateTimePicker1.Value = person.Birthday;
            textBox1.ReadOnly = true;
            textBox2.ReadOnly = true;
            textBox3.ReadOnly = true;
            textBox4.ReadOnly = true;
            textBox5.ReadOnly = true;
            textBox6.ReadOnly = true;
            dateTimePicker1.Enabled = false;
            toolStripButton5.Enabled = true;
        }

Funkcija 2 (Save button):

Code:
private void toolStripButton1_Click(object sender, EventArgs e)
        {
            Person person = FindPerson(listView1.SelectedItems[0].Text);
            if (listView1.SelectedItems.Count > 0)
            {
                person.Name = textBox1.Text;
                person.Hometown = textBox2.Text;
                person.Address = textBox3.Text;
                person.Phone = textBox4.Text;
                person.Email = textBox5.Text;
                person.Birthday = dateTimePicker1.Value;
                person.AdditionalInfo = textBox6.Text;
                listView1.SelectedItems[0].Text = textBox1.Text;
                textBox1.ReadOnly = true;
                textBox2.ReadOnly = true;
                textBox3.ReadOnly = true;
                textBox4.ReadOnly = true;
                textBox5.ReadOnly = true;
                textBox6.ReadOnly = true;
                dateTimePicker1.Enabled = false;
            }
            else
            {
                MessageBox.Show("Nothing is selected ", "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            UserCount();
        }

Ja se nadam da sam te dobro razumeo i da sam uradio to što si imao na umu.

Elem, kad startujem program, selektujem neki od kontakta i kada pokušam da selektujem nekog drugog, javlja se error:



Pored toga, kad hoću nekog da izbrišem, znači kad selektujem kontakt (i on "postane plav") i kliknem Remove, samo ga vrati u prvobitno stanje tj. kao da ga nisam selektovao, odnosno "nije više plav". Ali, kad izađem pa ponovo uđem, kontakt je izbrisan. Takođe, ponovo ostaje taj jedan kontakt, znači ako ih ima 5, mogu da obrišem 4; ako ih ima 100, mogu da obrišem 99. Ako ih recimo ima 5 i ja obrišem svih 5, pa izađem/uđem, svih 5 će ponovo biti tu. Znači, može sve osim jednog.

Hvala na nesebičnoj pomoći.
[ Mihajlo Cvetanović @ 20.11.2013. 15:05 ] @
Ako ništa nije selektovano onda nema smisla tražiti prvi selektovan element. Najpre nisam ni hteo da kažem gde treba da staviš "Person person = ..." liniju, a onda sam u drugom postu rekao da ona obično stoji na početku funkcije, ali nisam mislio da bude bukvalno prva linija.

Dakle, smeš da koristiš listView1.SelectedItems[0] isključivo ako si siguran da je listView1.SelectedItems.Count > 0. Ako je Count == 0 onda ne možeš da zoveš SelectedItems[0]. Verovatno bi se i sam uskoro dosetio ovoga.
[ Cal Lightman @ 20.11.2013. 15:53 ] @
Svaka čast Mihajlo, radi savršeno. Hvala ti mnogo.

Jedino što opet taj poslednji kontakt koji ostane pravi problem. Recimo da ima 5 kontakta i kada krenem sa brisanjem, obrišem 4 i kada ostane taj jedan poslednji, pokušam da ga selektujem i javi se error:



Ne znam šta je u pitanju...

Hvala još jednom!
[ AMD guy @ 20.11.2013. 18:34 ] @
Ne mozes da pristupis Name( i u tom slucaju bilo kom) property-ju ako nemas instancu klase Person.

Ako nista nije selektovano onda je index -1 a ti trazis index 0 koji ne postoji.
[ Cal Lightman @ 20.11.2013. 20:46 ] @
@AMD guy:

U potpunosti mi je jasno da je nezahvalno pričati sa nekim kada sagovornik ne poznaje osnove teme na koju se razgovor vodi, ali kako glasi kod koji bi to u praksi trebalo da ispravi? Kao što možeš i sam da pretpostaviš, od suve teorije nemam baš mnogo pomoći, mogu samo dalje da nastavim da lutam.

Hvala na javljanju svakako.
[ AMD guy @ 20.11.2013. 21:33 ] @
Hoces da kazes da ne poznajes osnove onoga cime se trenutno bavis ali ti je to trenutno ne vazno?
Zasto si se uputio u ovaj poduhvat pravljenja ove aplikacije?

Instanca se pravi sa pozivanjem new operatora, to ti i pise u Tips "Use new keyword to create an object instance"
Znaci

Code (csharp):
//new ti alocira memoriju gde ce biti objekat kreiran, a Person() je konstruktor tvoje Person klase
Person person = new Person();


sada kada kazes person.Name imaces pristup svim property-jima i metodama koje si tako deklarisao.

U tvom slucaju bi trebalo biti nesto ovako

Code (csharp):
Person person = new Person(); //Tvoja instanca
person = FindPerson(listView1.SelectedItems[0].Text);  //Ime tvoje osobe
textbox1.text = person.Name; // Koje ce se prikazati u textboxu


Da bi znao sta su Instance, konstruktori, properties morao bi malo da proucis Objektno orientisano programiranje, ja sam ucio iz ove knjige
http://knjige.kombib.rs/Objektno-orijentisani-nacin-misljenja

Ovi youtube tutoriali su mi uvek bili nekako povrsinski, srecom ja sam poceo da ucim iz knjige koja je imala neku strukturu.

Ako hoces da pravis neku aplikaciju, pre nego sto upalis visual studio stani malo, razmisli i opisi to sto zelis da ti aplikacija radi u nekoliko recenica.
Svaka imenica je potencijalna klasa, sta je odgovornost klase i kakvu saradnju ce imati ta klasa. Cim pocnes da dobijas ideju o tome tek onda mozes da upalis VS i pravis klase. To ti je deo opisa Objeknog programiranja koji je opisan u toj knjizi.

[Ovu poruku je menjao AMD guy dana 20.11.2013. u 22:43 GMT+1]
[ Cal Lightman @ 20.11.2013. 21:50 ] @
@AMD guy:

Hvala ti na pomoći, uspeo sam da rešim ovo.

Inače, da, hteo sam da kažem da ne poznajem osnove, ali ne vidim iz čega si izvukao da mi je to nevažno. To nisam nigde rekao, baš naprotiv. Stalno se trudim i svaki dan po nešto naučim, a to što nisam krenuo odakle je trebalo, to je druga priča - za osudu, slažem se. Aplikaciju sam krenuo da pravim iz čiste potrebe, sigurno ne da bih vas ovde i sebe zavitlavao. Nego, da se ne raspravljamo bezveze.

Hvala još jednom!
[ AMD guy @ 20.11.2013. 21:57 ] @
Malo mi je cudno da ne poznajes osnove a zelis da pravis aplikaciju ove velicine.

Citat:
Aplikaciju sam krenuo da pravim iz čiste potrebe, sigurno ne da bih vas ovde i sebe zavitlavao.

Ako je tako onda ok, ali ako te zanima sta i kako radi trebalo bi da uzmes neku knjigu.

Jel imas neku knjigu ili ucis iz ovih youtube tutoriala?
[ Cal Lightman @ 20.11.2013. 22:31 ] @
Nezadovoljan ponudom programa, ujedno smatrajući da neće biti mnogo komplikovano, upustih se u ovaj poduhvat, al' eto šta je ispalo na kraju. Što se kaže, obr'o sam bostan. Mislio sam da ću proći sa mnogo manje muka i da me u principu čeka jedino pravilno prepisivanje koda sa YT tutoriala, ali sam se dobrano uverio u suprotno i da su ti YT tutoriali, što kažeš, površni. Nemam nikakvu knjigu pred sobom, moraću da nabavim neku jer mi se programiranje dopada, uglavnom pravljenje aplikacija na ovu foru i web design. Ovo sam skrpio sa svih strana, baza je sa YT tutoriala, za svaku sitnicu koja mi je bila nejasna (a veruj mi, bilo ih je gomila) sam palio Google i tragao, raspitivao se i slično, što je ponekad znalo da traje i satima. Najbitniji deo ste mi odradili vi ovde na ES-u i na tome sam posebno zahvalan.