February 08, 2017

Alıntı (acehreli):

>
  • Düğmeyi ekleyip sonra ekleneni ayarlamak yerine zaten hazır düğme eklemeyi yeğlerim.
    [...]
>     düğmeler ~= düğmeYap(dil);
> ```

>

O zaman bu işlevin de pencere sınıfının işlevleri arasında görünmesine gerek olmayabilir diye düşünüyorum.

class Pencere: MainWindow
{
/* ... */

this()
{
/* ... */

   string[] programlamaDilleri = ["Java", "C++", "C", "Python", "Hiçbiri"];

   Button düğmeYap(string dil)
   {
       Button düğme = new Düğme(dil);
       düğme.addOnClicked(&seçimDüğmesiTıklandı);
       return düğme;
   }

   foreach (dil; programlamaDilleri)
   {
       düğmeler ~= düğmeYap(dil);
   }

   /* ... */

}
}



-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
February 08, 2017

Güzel. :) Sırf bir şeyler söylemiş olmak için:

  • Düğmeyi ekleyip sonra ekleneni ayarlamak yerine zaten hazır düğme eklemeyi yeğlerim. Yani, şunu değil:
   düğmeler ~= new Düğme(dil);
   düğmeler[i].addOnClicked(&seçimDüğmesiTıklandı);

Şunu yeğlerim:

   düğmeler ~= düğmeYap(dil);
  • Kendi adıma, tek deyim içeren bloklara bile kesinlikle küme parantezi kullanırım.
  • VeriModeli'ndeki bazı üye işlevleri yanılmıyorsam yalnızca kurulumu sırasında kullanılıyor. Dolayısıyla, arayüzünde görünmelerine gerek yok. En basiti, yazılımEkle() ve yazılımOku() this()'in içinde iç işlev olabilirler. Ama daha iyisi, this() parametre olarak Yazılım[] almalı... Böylece "veriler.txt"e bağımlı kalmamış olur. (Örneğin, böylece unittest sırasında dosyaya bağlı kalmadan istediğimizi verebiliriz.) Ek olarak, genel bir ilke olarak, kurucu işlev fazla karmaşık işlemlerle uğraşmamış olur.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 08, 2017

Koda tekrar bakıyorum... Ben olsam, "veriler.txt"i main'e (veya onun çağırdığı bir işleve) okuturum ve Yazılım[] dizisini Pencere.this'e veririm, ve o da VeriModeli'ne geçirir.

Aslında, VeriModeli'ni Pencere'nin oluşturması bile garip değil mi? O zaman bence VeriModeli'ni bile main oluşturmalı ve Pencere'ye onu vermeli.

Dediğim gibi, MVC kullanıcısı değilim ama her şeyin sınıflarla yapılması gerektiğini düşünmüyorum. Örneğin, yazılımlar'ın VeriModeli'nin üyesi olması gerekiyor mu? Sanki yalnızca setValue'ya veriliyor gibiler. (Belki ileride kullanılacaktır ama kodun bu haliyle ilerisi için saklanmasına gerek yok.)

İç işlevler kapsam içlerinde tanımlanan ve o kapsamlardaki değişkenleri kullanabilen işlevlerdir (yapılar ve sınıflar da var):

http://ddili.org/ders/d/ic_tanimlar.html

Çok yararlı bir olanak.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 08, 2017

Bana sorduğuna göre, kendi düşündüğüm gibi yanıtlıyorum: Kesinlikle! Önce normal işlev... Eğer verinin daha sonradan kullanılmak üzere saklanması gerekiyorsa, üye değişken... Eğer işlev veriyle doğrudan ilişkiliyse ve örneğin, Pencere kullanıcısı tarafından çağrılacaksa, bir başka deyişle, onun arayüzünün parçasıysa, ancak o zaman üye işlev...

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 08, 2017

düğmeYap() bu konuda ilginç çünkü farklı düşünülebilir:

  • Düğmenin nasıl olduğunu program belirliyorsa, yani Pencere'ye ait değilse, normal işlevi main dolaylı olarak çağırabilir.

  • Öte yandan, seçimDüğmesiTıklandı() Pencere'ye bağlı olduğundan burada aslında bu özel pencere tarafıdan oluşturulmalı. O yüzden bence Pencere'de kalması daha doğru.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 08, 2017

Ali beyin önerdiği değişikliklerden sonra kodun son hali şu şekilde oldu.

import gtk.Main;
import gtk.MainWindow;
import gtk.Box;
import gtk.ListStore;
import gtk.TreeView;
import gtk.TreeViewColumn;
import gtk.CellRendererText;
import gtk.TreeModelFilter;
import gtk.Grid;
import gtk.Button;
import gtk.ScrolledWindow;
import gtk.TreeModel;
import gtk.TreeIter;

import gobject.Value;

import std.format: formattedRead;
import std.stdio: File, writeln;

class Pencere: MainWindow
{
   Button[] düğmeler;
   string seçiliProgramlamaDili;
   GörünümModeli görünüm;
   TreeModelFilter süz;


   this (GörünümModeli görünüm)
   {
       super("Ağaç örneği");
       this.görünüm = görünüm;

       auto ızgara = new Grid();
       ızgara.setColumnHomogeneous(true);
       ızgara.setRowHomogeneous(true);
       add(ızgara);

       seçiliProgramlamaDili = "Hiçbiri";

       string[] programlamaDilleri = ["Java", "C++", "C", "Python", "Hiçbiri"];

       Button düğmeYap(string dil)
       {
           Button düğme = new Düğme(dil);
           düğme.addOnClicked(&seçimDüğmesiTıklandı);
           return düğme;
       }

       foreach (dil; programlamaDilleri)
       {
           düğmeler ~= düğmeYap(dil);
       }

       auto kayarPencere = new ScrolledWindow();
       kayarPencere.setVexpand(true);
       ızgara.attach(kayarPencere, 0, 0, 8, 10);
       ızgara.attachNextTo(düğmeler[0], kayarPencere, GtkPositionType.BOTTOM, 1, 1);

       foreach (i, düğme; düğmeler[1..$])
           ızgara.attachNextTo(düğme, düğmeler[i], GtkPositionType.RIGHT, 1, 1);
       kayarPencere.add(görünüm);

       showAll();

   }

   this (GörünümModeli görünüm, TreeModelFilter süz)
   {
       this.süz = süz;
       this(görünüm);
   }

   void seçimDüğmesiTıklandı(Button düğme)
   {
       seçiliProgramlamaDili = düğme.getLabel();
       if (seçiliProgramlamaDili != "Hiçbiri")
           writeln(seçiliProgramlamaDili, " dili seçildi!");
       else
           writeln("Hiç bir dil seçilmedi.");
       süz.refilter();
   }
}

struct Yazılım
{
   string isim;
   uint yıl;
   string dil;
}

class VeriModeli: ListStore /* model */
{
   this(Yazılım[] yazılımlar)
   {

       super([GType.STRING, GType.INT, GType.STRING]);

       void yazılımEkle(Yazılım yazılım)
       {
           auto erişici = createIter();
           setValue(erişici, 0, yazılım.isim);
           setValue(erişici, 1, yazılım.yıl);
           setValue(erişici, 2, yazılım.dil);
       }

       void yazılımlarıEkle(Yazılım[] yazılımlar)
       {

           foreach (yazılım; yazılımlar)
           {
               yazılımEkle(yazılım);
           }
       }

       yazılımlarıEkle(yazılımlar);
   }
}

class GörünümModeli: TreeView /* görünüm */
{
   this (ListStore model)
   {
       auto isimSütunu = new TreeViewColumn("İsim", new CellRendererText(), "text", 0);
       appendColumn(isimSütunu);
       auto yılSütunu = new TreeViewColumn("Yıl", new CellRendererText(), "text", 1);
       appendColumn(yılSütunu);
       auto dilSütunu = new TreeViewColumn("Dil", new CellRendererText(), "text", 2);
       appendColumn(dilSütunu);
   }
}

static extern(C) int dilleriSüz(GtkTreeModel * gtkModeli,
                               GtkTreeIter * gtkErişici, void * veriler)
{
   auto model = new TreeModel(gtkModeli, false);
   auto erişici = new TreeIter(gtkErişici, false);
   Pencere pencere = cast(Pencere) veriler;

   string dil = model.getValue(erişici, 2).dupString();

   if (pencere.seçiliProgramlamaDili == "Hiçbiri")
       return true;
   else
       return dil == pencere.seçiliProgramlamaDili;
}

Yazılım[] yazılımOku(string kütükİsmi)
{
   auto kütük = File(kütükİsmi, "r");
   Yazılım[] yazılımlar;
   foreach (satır; kütük.byLine())
   {
       string isim, dil;
       uint yıl;
       formattedRead(satır,"\"%s\", %d, \"%s\"", &isim, &yıl, &dil);
       yazılımlar ~= Yazılım(isim, yıl, dil);
   }
   return yazılımlar;
}


void main(string[] args)
{
   Main.init(args);
   auto yazılımlar = yazılımOku("veriler.txt");

   auto model = new VeriModeli(yazılımlar);

   auto süz = new TreeModelFilter(model, null);
   auto görünüm = new GörünümModeli(model);
   görünüm.setModel(süz);

   auto pencere = new Pencere(görünüm, süz);
   süz.setVisibleFunc(cast (GtkTreeModelFilterVisibleFunc) &dilleriSüz,
                      cast(void *)pencere, null);
   Main.run();
}

Yalnız burada Pencere sınıfına görünüm modelinden başka bir de süzme görevi yapan TreeFilter geçmiş olduk. O zaman bu durumda hem veri hem de görünümü kullanan ara bileşen ("Controller") ana sınıfımız oldu.

düğmeYap() konusunda ben de kararsız kaldım. Hatta ilk örnek bile kullanılabilir diye düşünüyorum.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 12, 2017

İşin içine süzme sıralama gibi işlemler de girince pencere sınıfının kurucu işlevi şuna benzemeye başlamıştı.

   this (GörünümModeli görünüm, VeriModeli model, TreeModelFilter süz, TreeModelSort sırala)
   {
       this.model = model;
       this.sırala = sırala;
       this.süz = süz;
       this(görünüm);
   }

Ben de bu sefer VeriModeli sınıfını basitçe yapı yaptım. İlk örneklerde VeriModeli bir ListStore'dan türüyordu. Bunu sahip olma ilişkisi olacak şekilde değiştirdim.

Her türlü yorum ve önerilerinizi bekliyorum.

import gtk.Main;
import gtk.MainWindow;
import gtk.Box;
import gtk.ListStore;
import gtk.TreeModelSort;
import gtk.TreeModelFilter;
import gtk.TreeView;
import gtk.TreeViewColumn;
import gtk.CellRendererText;
import gtk.Adjustment;
import gtk.SpinButton;
import gtk.TreeModel;
import gtk.TreeIter;
import gtk.CellRenderer;
import gtk.CellRendererText;
import gtk.TreePath;

import gobject.Value;

import std.stdio: writeln;
import std.format: format;

string liraYap(int kuruş)
{
   return "%.2f".format(cast (double) kuruş / 100);
}

class Pencere: MainWindow
{
   Box anaKutu;
   Görünüm görünüm;
   VeriModeli veri;
   double enYüksekFiyat;

   this(Görünüm görünüm, VeriModeli veri)
   {
       super("Ağaç örneği");

       this.görünüm = görünüm;
       this.veri = veri;

       anaKutu = new Box(Orientation.VERTICAL, 0);

       auto enYüksekFiyat = new Adjustment(10.99, 0.01, 1024.0, 0.01, 1.0, 0.0);
       auto kayarDüğme = new SpinButton(enYüksekFiyat, 1.0, 2);

       enYüksekFiyat.addOnValueChanged(&fiyatDeğişti);
       veri.süz.setVisibleFunc(cast (GtkTreeModelFilterVisibleFunc) &satırGörünürMü,
                               cast(void *)this, null);
       görünüm.addOnRowActivated(&sütünTıklandı);

       anaKutu.packStart(this.görünüm, true, true, 0);
       anaKutu.packStart(kayarDüğme, false, false, 0);

       add(anaKutu);

       showAll();
   }

   void fiyatDeğişti(Adjustment hizalama)
   {
       this.enYüksekFiyat = hizalama.getValue();
       veri.süz.refilter();
   }

   static extern(C) int satırGörünürMü(GtkTreeModel * gtkModeli,
                                       GtkTreeIter * gtkErişici, void * veriler)
   {
       auto model = new TreeModel(gtkModeli, false);
       auto erişici = new TreeIter(gtkErişici, false);
       Pencere pencere = cast(Pencere) veriler;

       int fiyat = model.getValue(erişici, 1).getInt();
       return cast (double) fiyat / 100 <= pencere.enYüksekFiyat;

   }

   void sütünTıklandı(TreePath iz, TreeViewColumn sütün, TreeView görünüm)
   {
       auto süzülmüşİz = veri.sırala.convertPathToChildPath(iz);
       auto gerçekİz = veri.süz.convertPathToChildPath(süzülmüşİz);

       TreeIter erişici = new TreeIter();

       if (veri.model.getIter(erişici, gerçekİz))
       {
           auto mal = veri.model.getValue(erişici, 0).dupString();
           auto fiyat = veri.model.getValue(erişici, 1).getInt();

           switch(mal)
           {
           case "Lokum":
               writeln(liraYap(fiyat), " e güzel lokumum var yer misin?");
               break;
           case "Üzüm":
               writeln("Taze üzüm geldi.", liraYap(fiyat), " lira");
               break;
           case "Karpuz":
               writeln("Kesmece karpuz ", liraYap(fiyat), " lira");
               break;
           case "Çorba":
               writeln("Mercimek çorbası içer misin?");
               break;

           default:
               writeln(mal, " ", liraYap(fiyat), " lira");
               break;
           }

       }
   }
}

struct Mal
{
   string isim;
   int fiyat;
};

class Görünüm: TreeView
{
   this(VeriModeli veri)
   {
       auto malSütunu = new TreeViewColumn("Mal", new CellRendererText(), "text", 0);
       malSütunu.setSortColumnId(0);
       appendColumn(malSütunu);

       auto fiyatGösterir = new CellRendererText();
       auto fiyatSütunu = new TreeViewColumn("Fiyat", fiyatGösterir, "text", 1);
       fiyatSütunu.setSortColumnId(1);
       appendColumn(fiyatSütunu);

       fiyatSütunu.setCellDataFunc(fiyatGösterir, cast(GtkTreeCellDataFunc)
                                   &fiyatSütununuGöster, null, null);

       setModel(veri.süz);

   }

   static extern(C) void fiyatSütununuGöster(GtkTreeViewColumn * treeColumn, GtkCellRenderer * cell,
                                             GtkTreeModel * gtkModeli, GtkTreeIter * iter, void * data)
   {
       auto model = new TreeModel(gtkModeli, false);
       auto erişici = new TreeIter(iter, false);
       auto hücreÇizici = new CellRenderer(cell, false);

       auto fiyat = model.getValue(erişici, 1).getInt();

       auto yeniFiyat = liraYap(fiyat);

       hücreÇizici.setProperty("foreground", "darkgreen");
       hücreÇizici.setProperty("text", yeniFiyat);
   }
}

struct VeriModeli
{
   ListStore model;
   TreeModelFilter süz;
   TreeModelSort sırala;

   this(Mal[] mallar)
   {
       model = new ListStore([GType.STRING, GType.INT]);
       süz = new TreeModelFilter(model, null);
       sırala = new TreeModelSort(süz);

       void malEkle(Mal mal)
       {
           auto erişici = model.createIter();
           model.setValue(erişici, 0, mal.isim);
           model.setValue(erişici, 1, new Value(mal.fiyat));
       }

       void mallarıEkle(Mal[] mallar)
       {
           foreach (mal; mallar)
           {
               malEkle(mal);
           }
       }
       mallarıEkle(mallar);
   }
}

Mal[]  mallarıEkle()
{
   Mal[] mallar;
   mallar ~= Mal("Ekmek", 100);
   mallar ~= Mal("Karpuz", 80);
   mallar ~= Mal("Lokum", 425);
   mallar ~= Mal("Çorba", 225);
   mallar ~= Mal("Üzüm", 325);
   mallar ~= Mal("Un", 515);
   return mallar;
}


void main(string[] args)
{
   Main.init(args);
   auto mallar = mallarıEkle();
   auto veri = VeriModeli(mallar);
   auto görünüm = new Görünüm(veri);
   auto pencere = new Pencere(görünüm, veri);
   Main.run();
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 12, 2017

Kusura kalmayın orada bir yazım hatası olmuş :)

Aslında oradaki 'static extern(C)' satırlarını kütüphanenin içine taşımanın bir yolunu bulabilsek güzel olacak. Dikkat ederseniz aslında sadece basitçe bir fiyat verisine erişiyor. GTK# ve PyGTK gibi kütüphaneler örneğin filtreleme için basitçe bir model ve erişiciyi parametre olarak göndermişler.

Benim kanaatime göre de bu 'static extern(C)' satırları kütüphanenin içinde olsa daha güzel olur. Ama şimdilik kafa yormadım.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 12, 2017

Bana güzel gözüktü.

Bu arada, "sütün" kelimesi nedense bana yazım kılavuzunu hatırlattı. ;)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

1 2
Next ›   Last »