28 Ocak 2015 Çarşamba

Docpad İle Statik Web Sayfası Hazırlamak

Web sitesi hazırlarken çoğu zaman statik bir web sitesi işimizi görecektir, hem server daha ucuz temin edilebilir. Ancak statik web sitesi hazırlarken en büyük sıkıntı, her sayfada yinelemek zorunda kalınılan menüler yerleşimler vs.

Bu konuda kısa bir araştırma yaptım, Docpad uygulamasını erb yapılara benzerliği yüzünden tercih ettim. Hadi beraber tutorial üzerinden gidelim.

Docpad node.js ile çalıştırılıyor , bu yüzden öncelikle sisteminizde node.js yüklü olmalıdır. Tavsiye en son sürüme yükseltip kullanmanız, bende 0.10.35 var.

Docpad Kurulumu

# npm install -g docpad@6.69
 Linux kullanıyorsanız sudo yetki gerekir.

Standart Proje Yapısını Oluşturmak

Web sitemizin içeriğine dalmadan önce proje klasörümüzü Docpad'in standart yapısına uygun olarak üretmemiz gerekiyor. Bunu yapmak için konsolda şunları yazın:
mkdir websitem cd websitem docpad run
ilk kez "docpad run" komutu girildiğinde lisans sözleşmesi çıkar ve "yes" için "y" girmenizi ister. Bu arada "docpad run" komutu sudo olarak çalıştırılmalı. Sonra sizden bir skeleton (iskelet yapı) kalıp seçmenizi ister. Biz "No Skeleton" seçeneği seçeceğiz. Birsürü yazılar geçtikten sonra sorun yoksa tüm klasör ve dosyaları hazırlayıp bir de server otomatik olarak çalışacaktır. Server yayınını http://localhost:9778 portundan yapmaya başlayacaktır. Tarayıcıyı çalıştırırsanız şimdilik sayfa olmadığı için "not found" dönecektir. Server'ı ne zaman durdurmak isterseniz Ctrl+C tuşlamanız yeterli. 


Anasayfa Eklenmesi

Hadi ilk sayfamızı oluşturalım. src/render/index.html dosyasını üretin ve içine şunları yazın:
<html>
<head>
    <title>Hoşgeldiniz! | Websitem</title>
</head>
<body>
    <h1>Hoşgeldiniz!</h1>
    <p>Websiteme hoşgeldiniz!</p>
</body>
</html>

Şimdi tarayıcıda http://localhost:9778 sayfasını yenilerseniz, kodunu yazdığınız sayfa görünür.

"Eee, ne oldu şimdi?, biz zaten html ile sayfa yazıyorduk" diyenler acık sabretsin.


Hakkında Sayfası ve bir Yerleşim Eklenmesi

Şimdi bir de "hakkımızda" sayfası koyalım ki , sitemizi ziyaret edenler kim olduğumuz konusunda bilgileri bizden alsın. Bu amaçla src/render/about.html adında yeni bir html döküman üretiyoruz.
<html>

<head>
    <title>Hakkımda | Websitem</title>
</head>
<body>
    <h1>Ben Kimim?</h1>
    <p>Her türlü program yazmayı severim. <strong>Ha bir de DocPad 
Kullanırım!</strong></p>
</body>
</html>

Yaşasııın, ikinci html sayfayı da yazdık. Tarayıcıda http://localhost:9778/about.html açınca bu sayfayı da görüntüleyebiliriz.

Fakat gördüğümüz gibi bir alt yapı var ve onu tekrarlayıp duruyoruz. 100 tane sayfa olsa biz de bu altyapıyı değiştirmeye kalksak 100 sayfada da değişiklik yapmak zorunda kalacağız. Mesela <head> kısmının içeriğini değiştirmek istiyoruz, bu durumda bütün dosyalarda değişiklik yapmamız gerekecek.

Layout'lar (yerleşimler) tüm dökümanı kapsarlar. Yerleşim değişince tüm dökümanlarda değişim olur. Uygulamamıza bir yerleşim tanımlamak için src/layouts/default.html.eco dosyasını üretip içine şunları yazalım:
<html>
<head>
    <title><%= @document.title %> | Websitem</title>
</head>
<body>
    <h1><%= @document.title %></h1>
    <%- @content %>
</body>
</html>

src/render/index.html
---
title: "Hoşgeldiniz!"
layout: "default"
isPage: true
---

<p>Websiteme hoşgeldiniz!</p>

src/render/about.html
---
title: "Hakkımda"
layout: "default"
isPage: true
---

<p>Her türlü program yazmayı severim. <strong>Ha bir de DocPad Kullanırım!</strong></p>
Ancaaak, server'ı kapatıp açıp sayfalarımıza tekrar baktığımızda yerleşime yazdığımız şeyleri görürüz, beklenen gibi kod çalışmaz. Çünkü daha "eco" yerleşim dosyalarını işleyecek eklentiyi yüklemedik.

Bunun dışında sayfalara "isPage" adında bir özellik ekledik. Şimdilik bu özellik DocPad için birşey ifade etmiyor, ilerde menüler vs. için kullanacağız.

Şablon Motorunun Kurulması

Bu klavuzda şablon motoru olarak eco kullanıyoruz. Şimdi bu plugin için konsolda şunları yazın:
docpad install eco
Plugin'i kurup server'ı tekrar çalıştırınca yerleşim şablon kodumuz çalışmaya başlayacaktır.

Peki neden döküman etiketinde (title) <%= kullandık da içeriği ifade ederken <%- kullandık? Sebebi şu, <%=
ile yazı içersindeki kod olabilecek özel karakterleri ayıklama yaparak yayınlar, <%- ise yazıyı olduğu gibi html koda ekler. Ne demeye çalıştığımı en iyi anlama yolu <%- yerine <%= yazarak "about.html" sayfasına bir bakın.                  


Live Reload (Anında Yükleme) plugin Yüklemek ve Bloklar

Her yaptığımız değişiklik için server'ı durdurup çalıştırmak gerekmesin diye "LiveReload" adında bir plugin var. Bunun sayesinde değişiklik yaptıkça tarayıcıda sayfayı tazelemek değişikliklerin işlenmesi için yeterli olacaktır.
docpad install livereload
Gelelim bloklara, bloklar sayesinde script'leri , stilleri ve metadata'ları sayfalarımıza yükleyebiliriz. Haydi default.html.eco yerleşimine 3 standart bloğu ekleyelim:
<html>
<head>
    <title><%= @document.title %> | Websitem</title>
    <%- @getBlock("meta").toHTML() %>
    <%- @getBlock("styles").toHTML() %>
</head>
<body>
    <h1><%= @document.title %></h1>
    <%- @content %>
    <%- @getBlock("scripts").toHTML() %>
</body>
</html>
Bu satırları ekledikten sonra bloklarda yapacağımız tüm değişiklikler otomatik olarak Live Reload sayesinde yüklenecektir.



Asset Eklemek

Resimler

Sayfamızın başına bir logomuzu ekleyelim. DocPad Logosunu indirin ve src/static/images/logo.gif dosyası olarak kaydedin.
  • src/layouts/default.html.eco
<html>
<head>
    <title><%= @document.title %> | Websitem</title>
    <%- @getBlock("meta").toHTML() %>
    <%- @getBlock("styles").toHTML() %>
</head>
<body>
    <img src="/images/logo.gif" />
    <h1><%= @document.title %></h1>
    <%- @content %>
    <%- @getBlock("scripts").toHTML() %>
</body>
</html>
Sayfayı tazeleyince logonun her iki sayfada da en üste geldiğini görürsünüz.

Stiller

Şimdi de h1 başlıklarımızı kırmızı yapalım. Stillerimizi render klasöründe src/render/styles/style.css dosyasına koyacağız. 
h1 {
  color: red;
}
Sonra da bu stili sayfalarımızda aktif etmek için default.html.eco yerleşim dosyasında şu değişikliği yapalım:
<%- @getBlock("styles").add(["/styles/style.css"]).toHTML() %>
Sayfalarımıza tekrar baktığımızda yeni stilimizin etkili olduğunu görürüz.


Scriptler

Şimdi sıra efektler için biraz JavaScript kullanmakta. Bu amaçla JQuery JavaScript kütüphanesini kullanacağız. 

İlk önce jQuery.js dosyasını indirin ve src/static/vendor/jquery.js olarak kaydedin. Şimdi bu faydalı kütüphaneyi websitemizde scriptlerde kullanacağız.

Sayfa yüklenirken yakışıklı bir efekt ekleyelim.  src/render/scripts/script.js dosyasını oluşturup içine :
(function(){
    $("body").hide().fadeIn(2000);
})();
Şimdi koyduğumuz script dosyalarını websitemiz içersin diye default.html.eco yerleşim dosyasında şu satırı değiştirelim:

    <%- @getBlock("scripts").add(["/vendor/jquery.js", "/scripts/script.js"]).toHTML() %>





Ön İşleyicilerin Faydaları

Ön işleyiciler harika şeyler. Dökümanları birtek dilde yazıp birçok değişik şekillere dönüştürmeye yararlar. En büyük faydası zorunlu olduğunuz bir dili değil hoşunuza giden dili kullanmanıza imkan verirler. 



HTML Önişleyicisi Olarak Markdown Kullanmak

Html kodlayarak bir web sayfası hazırlamak oldukça zor , okunması da zor bir iş. Çok şükür ki Markdown en önemli html önişleyici plugin olarak hizmetimizde. 

Marked Markdown Plugin yükleyerek başlayalım.
docpad install marked
Şimdi daha önce yazdığımız  render/about.html dosyasının adını render/about.html.md olarak değiştirelim. Böylece dosya içeriğinin Markdown için yazıldığını belirtiyoruz. Dosya içeriğini de şöyle düzenleyelim:
Her türlü program yazmayı severim. **Ha bir de DocPad Kullanırım!**
Gördünüz mü bir sürü html tag yerine daha anlaşılabilir sayfa içeriklerini Markdown formatında yazabiliriz. İşte statik web sitesi ile DocPad arasında en önemli farklardan ve avantajlardan biri.

Artık gazı aldık, sırada CSS stilleri kolaylaştırmak var.



CSS Önişleyici Olarak Stylus

Stylus başta gelen CSS önişleyicilerdendir.İşe Stylus Plugin yükleyerek başlayalım:
docpad install stylus
Sonra da  src/render/styles/style.css dosyasının adını src/render/styles/style.css.styl olarak değiştirelim. Neden bunları render klasörüne koyduk ta static klasörüne koymadık demişseniz, cevap burada. Static klasörü içine konan dosyalar önişleyicilerde işlenmeden aynen "out" klasörüne aktarılırlar. Şimdi stil dosyamızın içeriğini şöyle değiştirelim:
h1
  color: red
Sonuç aynı ama stil dosyamızda da işçiliklerden kurtulmaya başladık.




JavaScript Önişleyici Olarak CoffeeScript

Biliyorsunuz bu JavaScript yazımı çok karmaşık. Bir tane noktalı virgül unutursan arada , yandın. Bu karmaşıklığı önlemek için CoffeeScript icat edildi. 

CoffeeScript Plugin yükleyerek başlayalım:
docpad install coffeescript
Ardından  render/scripts/script.js dosyasının adını render/scripts/script.js.coffee olarak değiştirelim.

İçeriğini de şöyle değiştirelim:
$("body").hide().fadeIn(2000)
 Sonuç aynı ama artık CoffeeScript'in avantajları ve ferahlığıyla bir fincan kahve içebiliriz.






Bir Konfigürasyon Dosyası Yardımıyla Şablon Verisi ve Şablon Yardımcıları Eklemek

Konfigürasyon Dosyasının Amacı

DocPad konfigürasyon dosyası , bizim DocPad oluşumu websitemizin konfigüre etmemize yarar. Olayları takip eder ve yararlı faaliyetlerde bulunur.

Örneğin diyelim dökümana title tanımlamadık , bu durumda etiketimiz | Websitem şeklinde olacaktır. Böyle yarım yamalak olacağına etiketin "Benim Websitem" olmasını tercih ederiz. Bu amaçla "default.html.eco" yerleşim dosyamızda etiket satırını şöyle değiştirelim:
    <title><%= if @document.title then "#{@document.title} | Websitem" else "Benim Websitem" %> </title>
Bu kod değişikliği işimizi kısa yoldan halleder. Ama benzer olayların sayısı arttıkça hangisi hangi dosya içindeydi karmaşası başlayacaktır. Bunu önlemek için buna benzer işlemleri tek bir konfigürasyon dosyasına toplayıp sitemize bu dosyadan işlem yapmasını bildirmeliyiz.

DocPad'in tüm uygulama genelinde kullandığı konfigürasyon dosyası projemizin kök klasörü içindeki  /docpad.coffee dosyasıdır. Bu dosya DocPad ilk çalıştığında üretilmiş olmalıdır, eğer yoksa da bu isimde bir dosya üretip içine şunları yazın:
# DocPad Configuration File
# http://docpad.org/docs/config

# Define the DocPad Configuration
docpadConfig = {
 # ...
}

# Export the DocPad Configuration
module.exports = docpadConfig
Dikkat ederseniz bu dosya CoffeeScript ile yazılmış.


Şablon Verilerinin Kullanımı

Şablonlarımızda kullanılan tüm veriler konfigürasyon içinde templateData adıyla tanımlanır. Örneğin @document bizim şablon verimizin bir parçası. Şimdi etiket için bir şablon veri tanımlıyalım. Konfigürasyon dosyası içine şunları yazalım:
# Define the DocPad Configuration
docpadConfig = {
  templateData:
    site:
      title: "Benim Websitem"
}
Şimdi default.html.eco dosyamızı şu hale getirebiliriz:
    <title><%= if @document.title then "#{@document.title} | Websitem" else @site.title %> </title>
Ancak tabii ki biz bu lojiği de konfigürasyon içine kaydırmak isteyebiliriz.




Şablon Yardımcıları ile Lojiği Tanımlamak

Konfigürasyonu CoffeeScript dosyası ile tanımladığımızdan fonksiyon tanımlamalarını da burada yapabiliriz. Bunlara Şablon Yardımcıları (Template Helpers) denir. Bunlar sayesinde lojiği de ayrı olarak konfigürasyona kaydırabiliriz. Şimdi yerleşim dosyasındaki lojiği konfigürasyona taşıyalım. /docpad.coffee dosyasına şunu ekleyelim:
# Define the DocPad Configuration
docpadConfig = {
  templateData:
    site:
      title: "Benim Websitem"
   
    getPreparedTitle: -> if @document.title then "#{@document.title} | Websitem" else @site.title
}
Ardından da default.html.eco yerleşim dosyamızda:
    <title><%= @getPreparedTitle() %> </title>
değişikliğini yaptıkmı ilk şablon yardımcımızı yazmış ve de kullanmış oluruz.







Sayfalarımıza Menü Listeleri Eklemek

Bir menümüz olsa eklediğimiz sayfalar otomatikman menüye eklense ne güzel olur dimi? Tabiiki olur, hadi yapalım.

Yerleşimi Değiştirelim

src/layouts/default.html.eco yerleşim dosyamızı değiştireceğiz. h1 tag'i öncesine şunları ekleyelim:
    <img src="/images/logo.gif" />
    <ul>
        <% for page in @getCollection("html").findAll({isPage:true}).toJSON(): %>
            <li class="<%= if page.id is @document.id then 'active' else 'inactive' %>">
                <a href="<%= page.url %>">
                    <%= page.title %>
                </a>
            </li>
        <% end %>
    </ul>
    <h1><%= @document.title %></h1>
Menü listesi geldi. Tabii liste olarak , biraz CSS ister. Şimdi "isPage" şablon verisinin ne işe yaradığını gördük, o değer "true" olmazsa sayfa menülere çıkmaz.

Burada her sayfa için yerleşim içindeki bu koddan dolayı ayrı ayrı sayfa listesi sorgulanıp menü oluşturulacaktır. Halbuki sayfadan sayfaya geçerken değişen bir bilgi yok, o zaman bu sorgulamayı bir kere yapıp sonuçları sayfa kodunda değerlendirelim.


Sorgunun Konfigürasyon Dosyasında yapılması

DocPad konfigürasyon dosyamıza geri dönelim:
docpadConfig = {

    templateData:
        site:
            title"Benim Websitem"        

    getPreparedTitle: -> if @document.title then "#{@document.title} | Websitem" else @site.title

    collections:
        pages: ->
            @getCollection("html").findAllLive({isPage:true})
}

Sonra da yerleşim dosyamıza gidip "getCollection" satırını düzenliyoruz:
        <% for page in @getCollection("pages").toJSON(): %>

Arada farka dikkat ettiniz mi? Önce "finfAll" şimdi "findAllLive" kullandık. Böyle yapınca sorgumuz bir kere yapılıp sonrasında hep aynı bilgi kullanılıyor.

Sayfalarımız için Default Metadata oluşturmak

Şimdi her sayfaya yerleşim için "layout: default" yazmak istemezsek bunu da konfigürasyon dosyası içinde şöyle yaparız:
docpadConfig = {
    collections:
        pages: ->
            @getCollection("html").findAllLive({isPage:true}).on "add", (model) ->
                model.setMetaDefaults({layout:"default"})

}

Evet, her sayfaya "layout: default" yazmaktan da kurtulduk, başımız tavana erdi.


Benden bu kadar, "out" klasörü içindeki oluşturulan dosyaları herhangi bir web server'a yükledinizmi kullanıma hazır.

31 Aralık 2014 Çarşamba

WxPython Örnekler

İlk önce en basit uygulama :

# -*- coding: utf-8 -*-
import wx

app = wx.App()

frame = wx.Frame(None, -1, "BASİT")
frame.Show()

app.MainLoop()

 önce uygulama tanımlanıyor, sonra frame ile pencere tanımölanıyor. Sonrada frame görünür yapılıp, uygulama başlatılıyor.

Şimdi yazdığımız uygulamanın boyutunu ayarlayan satırlar. Bu sefer biraz daha yapısal bir uygulama yazılımı gösteriyoruz :

# -*- coding: utf-8 -*-
import wx

class Deneme(wx.Frame):
  
  def __init__(self, parent, title):
    super(Deneme, self).__init__(parent, title=title, size=(250, 200))
    
    self.Show()
    
if __name__ == "__main__" :
  app = wx.App()
  Deneme(None, title="Size")
  app.MainLoop()

Önce yukarıda Deneme adında yeni bir sınıfı Frame sınıfından üretip özelliklerinde boyutunu 250x200 pixel olarak ayarlıyoruz, sonra aşağıda uygulamayı çalıştırmaya yönelik kodları koyuyoruz. Bu aşağıdaki kısımda değişiklik yapmadan açılan pencere içeriğini yukarda sınıf tanımında yapmayı planlıyoruz.
Şimdi de ekranı ortalayalım :

# -*- coding: utf-8 -*-
import wx

class Deneme(wx.Frame):
  
  def __init__(self, parent, title):
    super(Deneme, self).__init__(parent, title=title, size=(300, 200))
    
    self.Centre()
    self.Show()
    
if __name__ == "__main__" :
  app = wx.App()
  Deneme(None, title="Merkezde")
  app.MainLoop()

İlk Menümüzü kullanalım bakalım :

# -*- coding: utf-8 -*-
import wx

class Deneme(wx.Frame):
  
  def __init__(self, *args, **kwargs):
    super(Deneme, self).__init__(*args, **kwargs)
    
    self.InitUI()
    
  def InitUI(self):
    menubar = wx.MenuBar()
    filemenu = wx.Menu()
    fitem = filemenu.Append(wx.ID_EXIT, "Çık", "Uygulamadan Çık")
    menubar.Append(filemenu, "&Dosya")
    self.SetMenuBar(menubar)
    
    self.Bind(wx.EVT_MENU, self.OnQuit, fitem)
    
    self.SetSize((300,200))
    self.SetTitle('Basit Menü')
    self.Centre()
    self.Show()
    
  def OnQuit(self, e):
    self.Close()
    
    
    
if __name__ == "__main__" :
  app = wx.App()
  Deneme(None)
  app.MainLoop()

Önce bir MenuBar tanımlıyoruz ki bu menünün tamamını oluşturur. İkinci olarak bir menü tanımlıyoruz, bu da menüde pencerede görünen menü başlıklarıdır. Son olarak menü içine eklenecek bir item tanımlıyoruz. wx.ID_EXIT ile standart uygulama çıkış menüsü item olarak ekleniyor. Menübar'a "Dosya" menüsü eklendikten sonra uygulamamıza işte bu senin menübar'ın diye gösteriyoruz.

Bind komutu ile tanımladığımız menü item tıklama olayını OnQuit metoduna bağlıyoruz. OnQuit metodu tanımlamasına da Close() yazarak uygulamadan çıkılmasını sağlıyoruz. Gerisi bildiğiniz şeyler :



İkonlar ve Kısayollar

# -*- coding: utf-8 -*-
import wx

APP_EXIT = 1

class Deneme(wx.Frame):
  
  def __init__(self, *args, **kwargs):
    super(Deneme, self).__init__(*args, **kwargs)
    
    self.InitUI()
    
  def InitUI(self):
    menubar = wx.MenuBar()
    filemenu = wx.Menu()
    qmi = wx.MenuItem(filemenu, APP_EXIT, "Çı&k\tCtrl+Q")
    qmi.SetBitmap(wx.Bitmap('images/exit.png'))
    filemenu.AppendItem(qmi)
    
    self.Bind(wx.EVT_MENU, self.OnQuit, id=APP_EXIT)
    
    menubar.Append(filemenu, '&Dosya')
    self.SetMenuBar(menubar)
    
    self.SetSize((300,200))
    self.SetTitle('İkonlar Kısayollar')
    self.Centre()
    self.Show()
    
  def OnQuit(self, e):
    self.Close()
    
    
    
if __name__ == "__main__" :
  app = wx.App()
  Deneme(None)
  app.MainLoop()


Ne fark var? bir wx.MenuItem tanımlıyoruz "k" harfine veya Ctrl+Q tuşlamasıyla da bu menü aktivasyonunun çalıştırılabileceği yönünde kısayol tanımları yapıyoruz. Bu hareketler bildiğiniz gibi tüm pencereli programlarda kullandığınız şeyler. Menüye bir de resim tanımlıyoruz. Bu esimleri nerde bulurum derseniz , linux kullananlar "/usr/share/" klasörü içinde "exit.png" aratırsanız diğer uygulamaların kullandığı ikonlardan bulabilirsiniz.findicons.com da bir sürü ikon var mesela böyle internetten de bulunabilir. Daha sonra Bind ile bu menüye "id" si üzerinden OnQuit metodunu bağlıyoruz.

Burada APP_EXIT ismi verilen bir sabit tanımlanmış ve onu kullanarak "id" üzerinden bağlantının nasıl yapıldığı gösterilmiştir. Burada APP_EXIT yerine isterseniz temsil ettiği "1" sayısını da kullanabilirsiniz, bu programın çalışmasını değiştirmez. Burada amaç hem size "id" üzerinden bağlantının nasıl kurulduğunu göstermek, aynı zamanda ilerde bissürü menü elemanınız olunca her birine ayrı numaraları verirken karıştırmamak için tüm "id" numaralandırmalarını programın bir noktasında toplamak.

Şunu unutmayın iş yapan bir uygulama yazmaya kalktığınızda bazen binlerce satır kod yazarsınız , burda kodun içinde kaybolmamak için bu şekil amacı belirten değişken isimleri ile çalışmak çok önemlidir. Değişkenlerin adı ne kadar uzun olursa olsun açıklayıcı olsun, nasıl olsa editörler iki-üç harf yazınca size önceden yazdığınız kelimeleri hatırlatmaya başlıyor.


Altmenüler ve Separatörler

# -*- coding: utf-8 -*-
import wx

class Deneme(wx.Frame):
  
  def __init__(self, *args, **kwargs):
    super(Deneme, self).__init__(*args, **kwargs)
    
    self.InitUI()
    
  def InitUI(self):
    menubar = wx.MenuBar()
    
    filemenu = wx.Menu()
    filemenu.Append(wx.ID_NEW, '&Yeni')
    filemenu.Append(wx.ID_OPEN, '&Aç')
    filemenu.Append(wx.ID_SAVE, '&Kaydet')
    filemenu.AppendSeparator()
    
    imp = wx.Menu()
    imp.Append(wx.ID_ANY, 'Newsfeed listesi al...')
    imp.Append(wx.ID_ANY, 'Bookmark al...')
    imp.Append(wx.ID_ANY, 'Mail al...')
    
    filemenu.AppendMenu(wx.ID_ANY, 'İçeri A&l', imp)
    qmi = wx.MenuItem(filemenu, wx.ID_EXIT, "Çı&k\tCtrl+Q")
    filemenu.AppendItem(qmi)
    
    self.Bind(wx.EVT_MENU, self.OnQuit, qmi)
    
    menubar.Append(filemenu, '&Dosya')
    self.SetMenuBar(menubar)
    
    self.SetSize((300,200))
    self.SetTitle('Alt Menü')
    self.Centre()
    self.Show()
    
  def OnQuit(self, e):
    self.Close()
    
    
    
if __name__ == "__main__" :
  app = wx.App()
  Deneme(None)
  app.MainLoop()



Bu uygulamada xwWidgets'in orjinal tanımlı menüleri ve ikonları kullanılmıştır. Bir listesi için tıklayın. Gördüğünüz gibi alt menü yapmak için yeni bir menü tanımlanıyor be bu menü sanki bir menü item gibi üst menüye ekleniyor. Bir de yeni olarak AddSeparator() komutu ile menüye bir grup ayırıcı yatay separatör konuyor.

Check Menü Elemanı

Üç çeşit menü elemanı vardır :
  1. Normal eleman
  2. Check Eleman
  3. Radio eleman
Şimdiye kadar kullandıklarımız normal menü elemanlarıydı. Şimdi Check menü elemanı örneği :

# -*- coding: utf-8 -*-
import wx

class Deneme(wx.Frame):
  
 def __init__(self, *args, **kwargs):
  super(Deneme, self).__init__(*args, **kwargs)
    
  self.InitUI()
    
 def InitUI(self):
  menubar = wx.MenuBar()
  filemenu = wx.Menu()
  viewmenu = wx.Menu()
    
  self.shst = viewmenu.Append(wx.ID_ANY, 'Statusbar Göster', 
              kind=wx.ITEM_CHECK)
  self.shtl = viewmenu.Append(wx.ID_ANY, 'Toolbar Göster', 
              kind=wx.ITEM_CHECK)
  
  viewmenu.Check(self.shst.GetId(), True)
  viewmenu.Check(self.shtl.GetId(), True)
    
  self.Bind(wx.EVT_MENU, self.ToggleStatusBar, self.shst)
  self.Bind(wx.EVT_MENU, self.ToggleToolBar, self.shtl)
  
  menubar.Append(filemenu, '&Dosya')
  menubar.Append(viewmenu, '&Görüntü')
  self.SetMenuBar(menubar)
  
  self.toolbar = self.CreateToolBar()
  self.toolbar.AddLabelTool(1, '', wx.Bitmap('images/exit.png'))
  self.toolbar.Realize()
  
  self.statusbar = self.CreateStatusBar()
  self.statusbar.SetStatusText('Hazır')
  
  self.SetSize((300,200))
  self.SetTitle('Check Menü Elemanı')
  self.Centre()
  self.Show()
    
 def ToggleStatusBar(self, e):
  if self.shst.IsChecked():
   self.statusbar.Show()
  else:
   self.statusbar.Hide()

 def ToggleToolBar(self, e):
  if self.shtl.IsChecked():
   self.toolbar.Show()
  else:
   self.toolbar.Hide()
  
  
  
if __name__ == "__main__" :
 app = wx.App()
 Deneme(None)
 app.MainLoop()

Oh oh herşey var, statusbar nasıl tanımlanır, toolbar nasıl tanımlanır, check menü elemanları.. Bir önemli ve kritik nokta daha var, bisürü "self" kelimesi neden? InitUi metodu içinde tanımladığımız elemanların özelliklerini diğer metodların içinde değiştirmek istiyoruz, o zaman bu elemanlara metod dışından erişilebilmesi için bunları sınıfa ait değişkenler olarak herbirinin başına "self" kelimesi koyarak tanımlıyoruz. Daha önce de aynı şekilde dışarıda tanımlanmış metodları çağırıyorduk hatırlarsanız.




Context Menü

Context menü sağ tuş tıklayınca çıkan menülere verilen addır:
# -*- coding: utf-8 -*-
import wx

class BenimPopupMenu(wx.Menu):
 def __init__(self, parent):
  super(BenimPopupMenu, self).__init__()
  
  self.parent = parent
  
  mmi = wx.MenuItem(self, wx.NewId(), 'Küçült')
  self.AppendItem(mmi)
  self.Bind(wx.EVT_MENU, self.OnMinimize, mmi)
  
  cmi = wx.MenuItem(self, wx.NewId(), 'Kapat')
  self.AppendItem(cmi)
  self.Bind(wx.EVT_MENU, self.OnClose, cmi)
 
 
 def OnMinimize(self, e):
  self.parent.Iconize()
  
 def OnClose(self, e):
  self.parent.Close()

class Deneme(wx.Frame):
  
 def __init__(self, *args, **kwargs):
  super(Deneme, self).__init__(*args, **kwargs)
    
  self.InitUI()
    
 def InitUI(self):
  self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
  
  self.SetSize((250,200))
  self.SetTitle('Context Menü')
  self.Centre()
  self.Show()
  
 def OnRightDown(self, e):
  self.PopupMenu(BenimPopupMenu(self), e.GetPosition())
  
  
if __name__ == "__main__" :
 app = wx.App()
 Deneme(None)
 app.MainLoop()




Toolbar

# -*- coding: utf-8 -*-
import wx


class Deneme(wx.Frame):
  
 def __init__(self, *args, **kwargs):
  super(Deneme, self).__init__(*args, **kwargs)
    
  self.InitUI()
    
 def InitUI(self):
  
  toolbar = self.CreateToolBar()
  qtool = toolbar.AddLabelTool(wx.ID_ANY, 'Çıkış', wx.Bitmap('images/exit.png'))
  toolbar.Realize()
  
  self.Bind(wx.EVT_TOOL, self.OnQuit, qtool)
  
  self.SetSize((250,200))
  self.SetTitle('Basit Toolbar')
  self.Centre()
  self.Show()
  
 def OnQuit(self, e):
  self.Close()
  
  
if __name__ == "__main__" :
 app = wx.App()
 Deneme(None)
 app.MainLoop()

CreateToolBar ile uygulamanın toolbar'ını tanımlıyoruz, ardından AddLabelTool ile çıkış simgesini toolbarımıza ekliyoruz. En son Realize komutuyla toolbar'ı ekranda gerçekleştiriyoruz.



Enable , disable

Toolbar objelerinin tıklanmasına izin vermek ya da vermemek.

# -*- coding: utf-8 -*-
import wx


class Deneme(wx.Frame):
  
 def __init__(self, *args, **kwargs):
  super(Deneme, self).__init__(*args, **kwargs)
    
  self.InitUI()
    
 def InitUI(self):
  
  self.count = 5
  
  self.toolbar = self.CreateToolBar()
  tundo = self.toolbar.AddLabelTool(wx.ID_UNDO,'',wx.Bitmap('images/undo.png'))
  tredo = self.toolbar.AddLabelTool(wx.ID_REDO,'',wx.Bitmap('images/redo.png'))
  self.toolbar.EnableTool(wx.ID_REDO,False)
  self.toolbar.AddSeparator()
  texit = self.toolbar.AddLabelTool(wx.ID_EXIT,'',wx.Bitmap('images/exit.png'))
  self.toolbar.Realize()
  
  self.Bind(wx.EVT_TOOL, self.OnQuit, texit)
  self.Bind(wx.EVT_TOOL, self.OnUndo, tundo)
  self.Bind(wx.EVT_TOOL, self.OnRedo, tredo)
  
  self.SetSize((250,200))
  self.SetTitle('Enable Disable')
  self.Centre()
  self.Show()
  
 def OnQuit(self, e):
  self.Close()
  
 def OnUndo(self, e):
  if self.count > 1 and self.count <= 5:
   self.count = self.count - 1
   
  if self.count == 1:
   self.toolbar.EnableTool(wx.ID_UNDO,False)
   
  if self.count == 4:
   self.toolbar.EnableTool(wx.ID_REDO,True)
   
 def OnRedo(self,e):
  if self.count < 5 and self.count >= 1:
   self.count = self.count + 1
   
  if self.count == 5:
   self.toolbar.EnableTool(wx.ID_REDO,False)
  
  if self.count == 2:
   self.toolbar.EnableTool(wx.ID_UNDO,True)
  
if __name__ == "__main__" :
 app = wx.App()
 Deneme(None)
 app.MainLoop()

Gördüğünüz gibi dışarıdaki metodlardan içerdeki tollbar'a müdahale ettiğimiz için yine bi sürü self kelimesi.





30 Aralık 2014 Salı

REBOL Örnekleri - 2

Hadi tekrar başlayalım :
REBOL [title: "ikinci kısım"]

view center-face layout [
    text "Merhaba 2. Kısım"
] 

center-face komutunu hangi nesneden evvel yazarsanız o nesne ta orta yere konur.
REBOL [title: "ikinci kısım"]

view layout [
    title "Merhaba Dünyalı"
] 

title stili ile başlık büyüklüğündeki puntolarla yazılır. Bir de BANNER ile nasılmış bakalım :
REBOL [title: "ikinci kısım"]

view layout [
    banner "Merhaba Dünyalı"
] 

Layout içinde birden çok stil tanımlayabiliriz. Bu örnek bir video heading (vh2) , bir text ve bir button içeriyor :
REBOL [title: "ikinci kısım"]

view layout [
    vh2 "Layout Tanımı:"
    text "Layoutlar grafik kullanıcı arabirimini (GUI) tanımlar."
    button "Hatırla"
]

Facet'ler yardımıyla bu stillere binlerce değişik efekt yapabiliriz :
REBOL [title: "ikinci kısım"]

view layout [
    backdrop effect [gradient 1x1 180.0.0 0.0.100]
    vh2 "Layout Tanımı:" 200x22 yellow
        effect [gradmul 1x0 50.50.50 128.128.128]
    vtext bold italic "Layoutlar grafik kullanıcı arabirimini (GUI) tanımlar."
    button "Hatırla" effect [gradient 0.0.0]
]


Layout içine ihtiyacınız kadar fazla sayıda stil atabilirsiniz. Mesela bu örnek bir backdrop, bir heading, text labellar, text input fieldler ve buttonlar içeriyor :
view layout [
    style lab label 100 right
    across
    vh2 "Bilgilerinizi Giriniz:" gold return
    lab "Kullanıcı Adı:" field return
    lab "Email Adresi:" field return
    lab "Tarih/Saat:" field form now return
    lab "Dosyalar:" text-list data load %. return
    lab
    button 96 "Kaydet"
    button 96 "İptal"
    return
]

Tanımlanmış REBOL stilleri şunlardır :
  • title  Döküman etiket başlığı .
  • h1 Dökümanda kullanılan ana başlık.
  • h2 Kısımları ayıran başlık.
  • h3 Alt kısımlar için başlık.
  • h4 Alt kısımların altındaki başlık.
  • h5 Alt kısımların altındaki başlık.
  • banner Video stillerin etiket başlığı.
  • vh1 Video stil kısımları ayıran başlık.
  • vh2 Video stil kısımları ayıran başlık.
  • vh3 Video stil kısımları ayıran başlık.
  • text Döküman gövde metni.
  • txt Yukardaki TEXT stili ile aynı.
  • vtext   Video stili gövde metni.
  • tt Sabit genişlikli teletype font.
  • code  TT ile aynı ancak koyu seçilmiş.
  • label  GUI içinde yazı satırları.
  • field Yazı giriş alanı.
  • info FIELD ile aynı ancak sadece okunabilir, yazılamaz.
  • area Text düzenleme alanı , paragraf giriş.
  • sensor Görünmeyen bir yüzey mouse hareketlerini algılamak için.
  • image JPEG, BMP, PNG, veya GIF resim gösterir.
  • box Dörtgen bir kutu çizer.
  • backdrop Bir resmi tüm layout penceresine yayar.
  • backtile Bir resmi tüm layout penceresinde tekrarlayarak kaplar.
  • icon Yazı başlıkla beraber bir ikon resmi gösterir.
  • led Bir gösterge ışığı.
  • anim  Animasyonlu bir resim gösterir.
  • button Standart tıklama düğmesi.
  • toggle Her tıkta konum değiştiren BUTTON .
  • rotary Birçok konuma tıklandıkça sırayla geçen buton.
  • choice popup ile birçok seçim sunan button.
  • check check box.
  • radio Yuvarlak radio button.
  • arrow Ok resimli button.
  • progress  Bir progress bar.
  • slider Slider bar.
  • panel Layout içinde layout.
  • list iterated alt-layout.
  • text-list Basit bir liste formu.
  • key Keyboard kısayolu
.

Ismarlama Stiller

Tüm yukarıdaki stiller istenilen şekilde facet'ler yardımıyla değiştirilebilir. Facet'ler yazıyı , boyutu , rengi, resimi değiştirebilir. Facet'ler isteğe bağlıdır, istediğinizi kullanırsınız. Aşağıda bir butona uygulanan çeşitli facet'ler gösterilmiştir:
view layout [
    button
    button "Easy"
    button "Easy" 40x40
    button "Easy" oldrab
    button "Easy" [print "Fun"]
    button "Easy" 40x40 maroon [print "Fun"]
]

Facet istenen sırada konabilir, kısıtlama olmadan istediğiniz şekilde kullanın, bir de hangisi önce yazılcaktı demeyin :
view layout [
    button "Easy" 40x40 navy [print "Fun"]
    button navy "Easy" 40x40 [print "Fun"]
    button 40x40 navy "Easy" [print "Fun"]
    button [print "Fun"] navy 40x40 "Easy"
]

Boyut Facet'leri

Boyutlar genişlik ve yüksekliği piksel olarak veren çiftler olabilir :
image %nyc.jpg 100x200
text "example" 200x200
button "test" 50x24
yada sadece genişliği verirler yükseklik stil içine göre otomatik ayarlanır :
text "example" 200
button "test" 50

Renk Facet'leri

Renkler kırmızı , yeşil , mavi karışımından oluşturulabilir.
image %palms.png 250.250.0
text "example" 0.0.200
button "test" 100.0.0
REBOL'un kullanabileceği 40 kadar ön tanımlı renk vardır :
text red "Warning"
text blue "Cool down"
text green / 2 "Ok"
Son satırda rengin parlaklığının nasıl kısıldığına dikkat ettiniz umarım. Bazı yüzeyler birden fazla renk alabilir, örneğin :
toggle "Test" red green

rotary "Stop" red "Caution" yellow "Go" green

Resim Facet'leri

Bir resim dosya adından internetten yada resim verisinden getirilebilir :
image %palms.png
image http://www.rebol.com/view/nyc.jpg
button "Test" %palms.png


Aksiyonlar

 Aksiyonlar blok olarak belirtilir. Aksiyonlar yüzeyleri hareketlendirir. Kullanıcı tıkladığında aksiyon bloğu içindeki program çalıştırılır :
image %nyc.jpg [print "Merhaba"]
text "Örnek" [print "Dünyalı"]
button "Test" [print "Kullanıcı"]
Bazı stiller ikinci bir blok alırlar , bu alternatif aksiyon içindir. Butona sol tıklanınca ilk, sağ tıklanınca ikinci aksiyon çalışır :
text "Buraya Tıkla" [print "Sol Tıkladın"] [print "Sağ Tıkladın"] 

Karakter Facet'ler

Bir kısayol tuşu bir tuşu string içinde ve başına # koyarak tanımlanır :
image %nyc.jpg #"a" [print "Merhaba"]
text "Örnek" #"^t" [print "Dünyalı"]
button "Test" #" " [print "Kullanıcı"]

 Facet Blokları

Facet blokları şekillendirme yaparken çok yararlıdır :


  • Font font bloğu kullanılan yazının özelliklerini belirler :

text "black" font [color: 255.255.255 size: 16 shadow: none]


  • Para bloğu yazının paragraf özelliklerini belirler :

text "test" para [origin: 10x10 margin: 10x10]

  •  Efect ile özel grafik efektler yapılır :

image %nyc.jpg effect [contrast 20]
image %nyc.jpg effect [tint 120 brighten 30]
button "Test" effect [gradient 0x1 200.0.0]

Size Kelimesi

Size ile layout boyutları belirlenir. Programda layout'un ilk satırlarında olmalıdır.
size 200x100
h2 "Size Örneği"

Eğer Size belirtilmemişse layout boyutu içine konan stillere göre otomatik ayarlanır :


Origin Kelimesi

Origin layout içindeki stillerin başlangıç noktası belirtilir. Default değeri 20x20 dir Aşağıda orjinalinden daha küçük origin değeri:
origin 4x2
text bold "Origin şimdi 4x2"


Şimdi de orjinalinden daha büyük origin :
origin 50
text bold "Origin şimdi 50x50"

 Değer belirtilmeyince origin default değerine döner:
box 34x40 beige
origin
text bold "Origin geri döndü"

Yukardaki örnekten görüldüğü üzere origin ile size belirtilmediği zaman layout boyutlarını da etkileyebiliyoruz.
Origin ayarı özellikle paneller ve listelerde çok önemlidir. Sıklıkla listlerin içinde origin 0 yapılır :
vh2 "Filmler:"
list 144x60 [
    origin 0
    across
    text 60
    text 80
] data [
    ["Back to the Future" "1:45"]
    ["Independence Day" "1:55"]
    ["Contact" "2:15"] ]

List'le birlikte verilen şekillendirme bloğunda origin 0 olarak verilmiştir.


Otomatik Layout Yönlendirmeleri

Below Kelimesi

Below kendisinden sonra gelen kısımda layout için dikey yerleştirme yapılacağını belirtir. ACROSS ile beraber layoutların otomatik yerleşimlerinde kullanılır:

Layout için BELOW default yerleşimdir :
button "Button 1"
button "Button 2"
button "Button 3"

Layout boyunca BELOW ve ACROSS ile yerleşimi düzenleyebilirsiniz :
across
button "Button 1"
button "Button 2"
below
button "Button 3"
button "Button 4"


Across Kelimesi

Across kendisinden sonra gelen stilllerin yatay yerleştirileceğini belirtir. Bir sonra gelen stil öncekinin sağına eklenir :
across
button "Button 1"
button "Button 2"
button "Button 3"

Layout boyunca across ve below arasında dönebilirsiniz :
vh2 "Örnek"
across
button "Button 1"
button "Button 2"
return
button "Button 3"
button "Button 4"
return

Return Kelimesi

Return layout yerleşim yönüne bağlı olarak bir sonraki satır ya da sütuna geçiş için kullanılır. layout yönü across ise return ile bir sonraki satıra geçilir, below ise bir yeni sütun açılır :
across
text "İsim:" 100x24 right
field "Adınızı Girin"
return
text "Adres:" 100x24 right
field "Adresinizi Girin"
return


Boşluklar

Space Kelimesi

Space kelimesi ile layout içindeki elemanların arasındaki otomatik boşluk işlemleri ayarlanır. Layout içinde herhangibir yerde boşluk ayarları değiştirilebilir. Boşluk ayarı bir çift değerle yada tek integer sayı ile yapılabilir : 
space 2x4
button "Button 1"
button "Button 2"
return
button "Button 3"
button "Button 4"


ikinci örnek daha büyük aralık içerir.
space 20x16
button "Button 1"
button "Button 2"
return
button "Button 3"
button "Button 4"



Pad Kelimesi

Bu kelime ile bir sonra gelen stil ile aradaki mesafe tayin edilir. Sanki etrafında verilen ebatlarda görünmeyen bir çevre varmış gibi sonraki stil ittirilir.
text "Bar below"
pad 20x4
box 50x3 maroon