#!/usr/bin/env python
# -*- coding: utf-8 -*-
u'''
Created on 13. 5. 2014
Program Imhotep v celé své kráse! Upgrade 1.1
@author: Stanislav Schütz
'''
import wx
class Bakala(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self,None,title=u'Program Imhotep pro pevnostní výpočet přírub')
        
        # Zavolá úvodní funkci
        self.uvod = Uvod(self)
        
        # Ošetření velikosti okna - při příliš velkém okně se zmenší právě na velikost mého rozlišení
        self.Maximize()
        a = self.GetSize()
        if a[0] > 1366 and a[1] > 740:
            a = (1366,740)
            self.Maximize(False)
            self.SetSize(a)
            self.CenterOnScreen() 
        
        # Tato je objekt lišty se Soubor atd
        menu = wx.MenuBar() 
        
        # Menu soubor
        menusoubor = wx.Menu() # Do tohoto objektu se ukládají ikonky v záložce Soubor
        menuOProgramu = menusoubor.Append(wx.ID_ABOUT,'O programu','Informace o tomto programu')
        menuZavrit = menusoubor.Append(wx.ID_EXIT, u'Ukončit',u'Ukončí program')
        menu.Append(menusoubor,'Soubor')
        
        # Menu výpočet
        menuvypocet = wx.Menu()
        menuOVypoctu = menuvypocet.Append(-1,u'O výpočtu',u'Zobrazí předpoklady pro výpočet')
        menuPocitej = menuvypocet.Append(-1,u'Počítej',u'Spustí výpočet')
        menu.Append(menuvypocet,u'Výpočet')
        self.SetMenuBar(menu) # A tímto se to povolá do Framu.
        
        self.CreateStatusBar() # Vytvoří se dole lišta
        
        # Události
        self.uvod.Bind(wx.EVT_CLOSE,self.Otevrit) # Otevře hlavní okno, zavře uvod
        self.Bind(wx.EVT_MENU,self.Zavrit,menuZavrit) # Zavře hl. okno
        self.Bind(wx.EVT_MENU,self.OProgramu,menuOProgramu) # Otevře info o programu
        self.Bind(wx.EVT_MENU,self.OVypoctu,menuOVypoctu) # Otevře okno s návodem
        self.Bind(wx.EVT_MENU,self.Pocitej,menuPocitej) # Spustí výpočet z Panelu nástrojů
        
        
    def Vykresleni(self):
        u"""Funkce po zavolání vykreslí panely"""
        
        # Rozložení panelů programu přes wx.LayoutConstraints
        panel = wx.Panel(self,-1) # Panel, do kterého se vloží okna
        panel.SetAutoLayout(True)
        panelVstupy = wx.Window(panel, -1, style=wx.SIMPLE_BORDER) # Okno, kam se přidají vstupy pro geometrii
        rozlozeniGeom = wx.LayoutConstraints() # Definuje rozložení v rámci panelu
        rozlozeniGeom.top.SameAs(panel, wx.Top, 5)
        rozlozeniGeom.left.SameAs(panel, wx.Left, 5)
        rozlozeniGeom.bottom.SameAs(panel, wx.Bottom, 5)
        rozlozeniGeom.right.PercentOf(panel, wx.Right, 40)
        panelVstupy.SetConstraints(rozlozeniGeom) # Použije rozložení pro daný panel
        
        # Okno, kam se dá obrázek v závislosti na typu příruby
        self.pObr = panelObr = wx.Window(panel, -1, style=wx.SIMPLE_BORDER) 
        rozlozeniGeom = wx.LayoutConstraints()
        rozlozeniGeom.top.SameAs(panel, wx.Top, 5)
        rozlozeniGeom.left.RightOf(panelVstupy, 5)
        rozlozeniGeom.right.SameAs(panel, wx.Right, 5)
        rozlozeniGeom.bottom.SameAs(panel, wx.Bottom, 5)
        panelObr.SetConstraints(rozlozeniGeom)
        
        # Rozdělení panelu vstupy na jednotlivé panely do sloupcového sizeru
        box = wx.BoxSizer(wx.VERTICAL)
        pObrazek = wx.Window(panelObr, style=wx.SIMPLE_BORDER)
        pSpusteni = wx.Window(panelObr, style=wx.SIMPLE_BORDER)
        box.Add(pObrazek, 7, wx.EXPAND,2)
        box.Add(pSpusteni, 3, wx.EXPAND,2)
        panelObr.SetSizer(box)  # Použije sizer pro daný panel/okno
        
        # Nahraje obrázek dle typu
        if self.typ == 1:
            obr = wx.Bitmap('typ_i.jpg')
        elif self.typ == 2:
            obr = wx.Bitmap('typ_ii.jpg')
        elif self.typ == 3:
            obr = wx.Bitmap('typ_iii.jpg')
        else:
            self.Destroy()
        
        wx.StaticBitmap(pObrazek,-1,obr)
        
        # Tlacitko pro spusteni
        b = wx.Button(pSpusteni,-1,u'Počítej',size = (120,40),pos = (300,30))
        fontTlac = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
        fontTlac.SetWeight(wx.FONTWEIGHT_BOLD)
        b.SetFont(fontTlac)

        
        # Rozdělení panelu vstupy na jednotlivé panely do sloupcového sizeru
        box = wx.BoxSizer(wx.VERTICAL)
        pGeom = wx.Window(panelVstupy, style=wx.SIMPLE_BORDER)
        pTes = wx.Window(panelVstupy, style=wx.SIMPLE_BORDER)
        pMat = wx.Window(panelVstupy, style=wx.SIMPLE_BORDER)
        box.Add(pGeom, 5, wx.EXPAND,2)
        box.Add(pTes, 2, wx.EXPAND,2) # První číslo udává počet "dílků", které panel zabírá
        box.Add(pMat, 3, wx.EXPAND,2) # expand a druhé číslo pravděpodobně nefungují
        panelVstupy.SetSizer(box)  # Použije sizer pro daný panel/okno
        
        
        # Ted velká věc - jdu zadat geometrické veličiny
        veliciny = 'A B C G e g_0 g_1 h d n'
        #DIN = '220 100 180 140 17 3.6 8.5 20 16 8' # PN 16
        DIN = '235 100 190 170 21 3.6 9.85 29 20 8' # PN 40
        CSN = '215 109 180 158 21 4 10 6 18 8'
        if self.typ == 2:
            priruba = CSN
        else:
            priruba = DIN
        jednotky = u'mm mm mm mm mm mm mm mm mm počet'
        geom = veliciny.split()
        priruba = priruba.split()
        jedno = jednotky.split()
        
        # Vkládání objektů do GridBagSizeru
        mrizkovySizer = wx.GridBagSizer(vgap = 4, hgap =4)
        text = wx.StaticText(pGeom,-1, u'Geometrie příruby')
        font = wx.Font(10.4, wx.DEFAULT, wx.NORMAL, wx.NORMAL) # vytvořím nadpisový font
        font.SetUnderlined(True)
        font.SetWeight(wx.FONTWEIGHT_BOLD)
        text.SetFont(font)
        mrizkovySizer.Add(text, (0,0), (1,3), wx.ALIGN_CENTER | wx.ALL, 5)
        
        self.hodnoty={}
        
        for x in range(len(geom)): # Projede veličiny,DIN a jednotky a nastřílí je do sizeru
            popis = wx.StaticText(pGeom,-1,'  '+geom[x]+' =')
            vstup = wx.TextCtrl(pGeom,-1, priruba[x])
            jednotka = wx.StaticText(pGeom,-1,jedno[x])
            mrizkovySizer.Add(popis,(x+1,0), flag=wx.ALIGN_RIGHT, border=15) # flagy nevím jestli fungují...
            mrizkovySizer.Add(vstup,(x+1,1), flag=wx.ALIGN_CENTER | wx.EXPAND)
            mrizkovySizer.Add(jednotka,(x+1,2), flag=wx.ALIGN_LEFT, border=15)
            self.hodnoty[geom[x]]=vstup # zápis do slovníku hodnoty
        
        # Tloustka polotovaru - spočtu z geometrie v závislosti na typu
        if self.typ != 2:
            e = float(self.hodnoty['e'].GetValue())
            h = float(self.hodnoty['h'].GetValue())
            self.tmin = e+h+2
        else:
            e = float(self.hodnoty['e'].GetValue())
            self.tmin = e+2
        popis = wx.StaticText(pGeom,-1,'  t =')
        vstup = wx.TextCtrl(pGeom,-1, str(self.tmin)) # Toto by se dalo udělat jako fce, viz Raadek ve vystup.py
        jednotka = wx.StaticText(pGeom,-1,'mm')
        mrizkovySizer.Add(popis,(1,3), flag=wx.ALIGN_RIGHT, border=15) # flagy stále nefungují
        mrizkovySizer.Add(vstup,(1,4), flag=wx.ALIGN_CENTER | wx.EXPAND)
        mrizkovySizer.Add(jednotka,(1,5), flag=wx.ALIGN_LEFT, border=15) # Dvojčíslí je pozice (radek,sloupec) v sizeru
        self.hodnoty['t']=vstup 

        # Poznámky k veličinám
        mrizkovySizer.Add(wx.StaticText(pGeom,-1,'  Pozn:'),(3,3),(1,3))
        poznG = u'  Za G bereme střední průměr těsnění'
        poznt1 = u'  t je tloušťka polotovaru pro výrobu příruby,'
        poznt2 = u'      ta rozhoduje o mech. vlastnostech materiálu'
        mrizkovySizer.Add(wx.StaticText(pGeom,-1,poznG),(4,3),(1,3))
        mrizkovySizer.Add(wx.StaticText(pGeom,-1,poznt1),(5,3),(1,3)) # Druhé dvojčíslí je kolik pozic pole zabírá (radek,sloupec)
        mrizkovySizer.Add(wx.StaticText(pGeom,-1,poznt2),(6,3),(1,3))
        
        pGeom.SetSizer(mrizkovySizer) # Aktivuje sizer
        
        
        # Zadání těsnění
        mrizkovySizer = wx.GridBagSizer(vgap = 4, hgap =4) 
        text = wx.StaticText(pTes,-1,u'Těsnění')
        text.SetFont(font) # Jen využiju výše definovaný font
        mrizkovySizer.Add(text, (0,0), (1,3), wx.ALIGN_CENTER | wx.ALL, 5)
        
        velic = ['w','m','y']
        tes = ['6','3.25','37.9']
        jedno = ['mm','-','MPa']
        
        self.tes={}
        
        for x in range(len(velic)): # Projede veličiny, tes a jednotky a nastřílí je do sizeru
            popis = wx.StaticText(pTes,-1,'  '+velic[x]+' =')
            vstup = wx.TextCtrl(pTes,-1, tes[x])
            jednotka = wx.StaticText(pTes,-1,jedno[x])
            mrizkovySizer.Add(popis,(x+1,0),flag=wx.ALIGN_RIGHT)
            mrizkovySizer.Add(vstup,(x+1,1))
            mrizkovySizer.Add(jednotka,(x+1,2))
            self.tes[velic[x]]=vstup 
        
        pTes.SetSizer(mrizkovySizer)


        # Zadání materiálu
        mrizkovySizer = wx.GridBagSizer(vgap = 4, hgap =4)    
        self.material={}
        
        text = wx.StaticText(pMat,-1, u' Materiál příruby')
        font2 = wx.Font(10.4, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
        font2.SetWeight(wx.FONTWEIGHT_BOLD)
        text.SetFont(font2)
        mrizkovySizer.Add(text, (0,0))
        seznamMater = ['P235GH','P355GH','20MnMoNi4-5','12CrMo9-10']           
        priruba = wx.Choice(pMat, -1, (200, 50), choices = seznamMater)       
        mrizkovySizer.Add(priruba,(0,1))
        
        # Mimo typ 1 se příruba skládá ze dvou částí, které můžou být z různých materiálů
        if self.typ != 1:
            text = wx.StaticText(pMat,-1, u' Materiál pláště')  
            text.SetFont(font2)
            mrizkovySizer.Add(text, (1,0))
            plast = wx.Choice(pMat, -1, (200, 50), choices = seznamMater)       
            mrizkovySizer.Add(plast,(1,1))
            x = 1
            
            self.Bind(wx.EVT_CHOICE, self.VyberMatPlast, plast) # předsunutý event, který přiřadí materiál plášti
        else:
            x = 0 # Pozice zbytku bude o jedno výš
        
        self.mat = {}
        # Materiálové charakteristiky pro šrouby
        popis = wx.StaticText(pMat,-1,u'Mez kluzu šroubů pro montážní teplotu')
        vstup = wx.TextCtrl(pMat,-1, '300')
        jednotka = wx.StaticText(pMat,-1,'MPa')
        mrizkovySizer.Add(popis,(x+1,0),flag=wx.ALIGN_RIGHT)
        mrizkovySizer.Add(vstup,(x+1,1))
        mrizkovySizer.Add(jednotka,(x+1,2))
        self.mat['Re_BA']=vstup
        
        x += 1
        popis = wx.StaticText(pMat,-1,u'Mez kluzu šroubů pro provozní teplotu')
        vstup = wx.TextCtrl(pMat,-1, '270')
        jednotka = wx.StaticText(pMat,-1,'MPa')
        mrizkovySizer.Add(popis,(x+1,0),flag=wx.ALIGN_RIGHT)
        mrizkovySizer.Add(vstup,(x+1,1))
        mrizkovySizer.Add(jednotka,(x+1,2))
        self.mat['Re_B']=vstup 
        
        x += 1
        popis = wx.StaticText(pMat,-1,u' Mez pevnosti šroubů pro 20 °C')
        vstup = wx.TextCtrl(pMat,-1, '500')
        jednotka = wx.StaticText(pMat,-1,'MPa')
        mrizkovySizer.Add(popis,(x+1,0),flag=wx.ALIGN_RIGHT)
        mrizkovySizer.Add(vstup,(x+1,1))
        mrizkovySizer.Add(jednotka,(x+1,2))
        self.mat['Rm']=vstup 
        
        pMat.SetSizer(mrizkovySizer)
        
        
        # Zadání zatížení
        mrizkovySizer = wx.GridBagSizer(vgap = 4, hgap =4)
        text = wx.StaticText(pSpusteni,-1, u'Zátěžný stav')
        text.SetFont(font)
        mrizkovySizer.Add(text, (0,0), (1,3), wx.ALIGN_CENTER | wx.ALL, 5)
        
        # Ruční zapsání ted už tří polí pro zatížení (zlatý for...)
        p = wx.StaticText(pSpusteni,-1,'  p = ')
        T = wx.StaticText(pSpusteni,-1,'  T_prov = ')
        T_mont = wx.StaticText(pSpusteni,-1,'  T_mont = ')
        if self.typ == 2: # Pro typ 2 je nejvyšší normovaná příruba PN 16, tj 1,6 MPa
            vstupP = wx.TextCtrl(pSpusteni,-1,'1.6')
        else:
            vstupP = wx.TextCtrl(pSpusteni,-1,'4')
        vstupT = wx.TextCtrl(pSpusteni,-1,'100')
        vstupT_mont = wx.TextCtrl(pSpusteni,-1,'20')
        jednotP = wx.StaticText(pSpusteni,-1,'MPa')
        jednotT = wx.StaticText(pSpusteni,-1,u'°C')
        jednotT_mont = wx.StaticText(pSpusteni,-1,u'°C')
        mrizkovySizer.Add(p,(1,0),flag=wx.ALIGN_RIGHT)
        mrizkovySizer.Add(vstupP,(1,1))
        mrizkovySizer.Add(jednotP,(1,2))
        mrizkovySizer.Add(T,(2,0),flag=wx.ALIGN_RIGHT)
        mrizkovySizer.Add(vstupT,(2,1))
        mrizkovySizer.Add(jednotT,(2,2))
        mrizkovySizer.Add(T_mont,(3,0),flag=wx.ALIGN_RIGHT)
        mrizkovySizer.Add(vstupT_mont,(3,1))
        mrizkovySizer.Add(jednotT_mont,(3,2))
        
        self.zatiz = {'P': vstupP,      # Toto reprezentuje wx.objekty, kde jsou vstupy 
                      'T_prov': vstupT,
                      'T_mont': vstupT_mont}
        
        pSpusteni.SetSizer(mrizkovySizer)
        
        
                
        # Události
        self.Bind(wx.EVT_BUTTON,self.Pocitej,b) # Spustí výpočet
        self.Bind(wx.EVT_CHOICE, self.VyberMatPriruba, priruba) # Výběr materiálu     
           
    def VyberMatPriruba(self,e):
        if e.GetString() == 'P235GH':
            self.material['matPriruba'] = 1
        elif e.GetString() == 'P355GH':
            self.material['matPriruba'] = 2
        elif e.GetString() == '20MnMoNi4-5':
            self.material['matPriruba'] = 3
        elif e.GetString() == '12CrMo9-10':
            self.material['matPriruba'] = 4
        
    def VyberMatPlast(self,e):
        if e.GetString() == 'P235GH':
            self.material['matPlast'] = 1
        elif e.GetString() == 'P355GH':
            self.material['matPlast'] = 2
        elif e.GetString() == '20MnMoNi4-5':
            self.material['matPlast'] = 3
        elif e.GetString() == '12CrMo9-10':
            self.material['matPlast'] = 4
        
    def Pocitej(self,e):
        u"""Provede výpočet se i všemi kontrolami"""
        nadpis = (u'NEPLATNÝ VSTUP') # Nadpis společný pro většinu hlášení
        
        # Úsek, kdy zapíšu vše ze vstupů do slovníků
        try:
            hodnoty = {} 
            for clen in self.hodnoty.keys():
                hodnoty[clen] = float(self.hodnoty[clen].GetValue())
            self.geom = hodnoty # Sem se zapíšou geom hodnoty pro výpočet
            
            tesneni = {} 
            for clen in self.tes.keys():
                tesneni[clen] = float(self.tes[clen].GetValue())
            self.tesneni = tesneni # Sem se zapíšou hodnoty těsnění
            
            # Zde jinak, protože self.mat jsou 2 vstupy pro převod a self.material už existuje s hodnotama z výběru
            for clen in self.mat.keys():
                self.material[clen] = float(self.mat[clen].GetValue())
            
            zatizeni = {}
            for clen in self.zatiz.keys():
                zatizeni[clen] = float(self.zatiz[clen].GetValue())
            self.zatizeni = zatizeni # Sem se zapíšou hodnoty zatíženi
            
        # Toto ošetří případ, kdy bude vstupem něco jiného než číslo    
        except ValueError: 
            zprava = (u"Jako vstup může posloužit pouze číslo,"
                            u"\nkde se místo desetinné čárky používá tečka.")
            self.Hlaseni(zprava,nadpis)
            return None
        
        # Nyní úsek VŠECH kontrol, kde si nejdřív musím vytáhnout veličiny ze slovníků
        t = self.geom['t']
        T_prov = self.zatizeni['T_prov']
        T_mont = self.zatizeni['T_mont']
        P = self.zatizeni['P']
        Re_B = self.material['Re_B']
        Re_BA = self.material['Re_BA']
        e = self.geom['e']
        h = self.geom['h']
        if self.typ == 2:
            tmin = e+2
        else:
            tmin = e+h+2
        g_0 = self.geom['g_0']
        g_1 = self.geom['g_1']
        
        # Ošetření hodnot, pro které nelze dosadit do fce Mat()
        if T_prov <= 0 or T_mont <= 0:
            zprava = (u'Za mez kluzu se bere hodnota určená při 20 °C'
                      u'\n\nSkutečné chování materiálu tomu nemusí odpovídat.'
                      u'\nDejte pozor na možnost křehkého lomu.')
            self.Hlaseni(zprava,u'UPOZORNĚNÍ')
        elif T_prov > 400 or T_mont > 400:
            zprava = (u'Hodnoty pro teploty větší než 400 °C nejsou pro tento materiál tabelované.'
                      u'\n\nSnižte teplotu.')
            self.Hlaseni(zprava,nadpis)
            return None
        elif t > 150:
            zprava = (u'Hodnoty pro tloušťku větší než 150 mm nejsou tabelované.'
                      u'\n\nZmenšete tloušťku.')
            self.Hlaseni(zprava,nadpis)
            return None
        elif P < 0:
            zprava = (u'Nelze počítat se záporným tlakem.')
            self.Hlaseni(zprava,nadpis)
            return None
        
        # Hlášení pro malou tlouštku polotovaru 
        if t < tmin:
            zprava = (u'Tloušťka polotovaru musí mít minimální hodnotu'
                      u'\n' + str(tmin) + ' což plyne z geometrie a přídavku na obrábění.')
            self.Hlaseni(zprava,u'ŠPATNÁ TLOUŠŤKA POLOTOVARU')
            return None
        # Podmínka 4 šroubů
        elif float(self.hodnoty['n'].GetValue()) < 4.0:
            zprava = (u'Minimální počet šroubů je 4')
            self.Hlaseni(zprava,nadpis)
            return None
        # Rovnají-li se teploty, musí se rovnat i meze kluzu pro šrouby
        elif T_prov == T_mont and Re_B != Re_BA:
            zprava = (u'Montážní a provozní teplota se sobě rovnají. To znamená, že není teplotní'
                      u'\nrozdíl mezi oběma stavy a tak šrouby musí mít stejnou mez kluzu pro oba případy.'
                      u'\n\nZměňte meze kluzu šroubů.')
            self.Hlaseni(zprava,nadpis)
            return None
        # Podmínka stoupání krku
        elif self.typ != 3:
            if g_1 > (g_0+h):
                zprava = (u'Pro tento typ příruby musí být splněna následující podmínka:'
                          u'\n       g_1 <= (g_0+h)')
                self.Hlaseni(zprava,u"PODMÍNKA STOUPÁNÍ KRKU")
                return None
        
        # Provedení samotného výpočtu, dojde k němu, pokud program dosud nenarazil na return None
        try:
            import vypocet
            
            vysledek = vypocet.Vypocet(self.typ,self.geom,self.tesneni,self.material,self.zatizeni)
            
        except KeyError: # Když bude ve výpočtu chybět hodnota ve slovníku, zahlásí totok
            zprava = (u"Chybí některé údaje."
                      u"\n\nZkuste znovu zadat materiál")
            self.Hlaseni(zprava,nadpis)
            
        except ZeroDivisionError: # Dojde-li k dělení nulou (hodnota vstupu může být 0, není ošetřeno)
            zprava = (u"Došlo k dělení nulou."
                      u"\n\nOvěřte, zda všechny zadané hodnoty jsou správné")
            self.Hlaseni(zprava,nadpis)
        
        # Připsání zatížení do slovníku pro výstupní okno 
        vysledek['P'] = self.zatizeni['P']
        vysledek['T_prov'] = self.zatizeni['T_prov']
        vysledek['T_mont'] = self.zatizeni['T_mont']
        print vysledek # Dá kompletní výpis hodnot, možná do budoucna vykomentovat
        
        # Kontrola, či jsou oba momenty kladné - částečně zabrání nesmyslným vstupům od uživatele
        if vysledek['M_op'] < 0 or vysledek['M_A'] < 0:
            zprava = (u"Provozní moment vyšel záporný."
                      u"\n\nOvěřte, zda všechny zadané hodnoty jsou správné")
            self.Hlaseni(zprava,nadpis)
        else:
            VystupniOkno(self,vysledek)                
        
    def Zavrit(self,e): 
        self.Close(True)
        
    def Otevrit(self,e):
        u"""Zavře okno Uvod a otevře/vykreslí hlavní okno, tj Bakala"""
        self.typ = self.uvod.typ      
        if self.typ == None:
            self.Destroy()
        else: 
            self.uvod.Destroy()
            
        self.Vykresleni()
        self.Show()
        
    def OProgramu(self,e):
        info = wx.AboutDialogInfo()
        info.Name = "Imhotep"
        info.Copyright = u"(C) 2014 Stanislav Schütz, FSI VUT v Brně"
        info.SetDescription(u"\nTento program slouží pro pevnostní výpočet přírub dle normy ČSN EN 13445-3,"
         u"\nkterýžto byl vytvořen jako část bakalářské práce."
         u"\n\nVšechna práva jsou mi ukradena, budu rád, když program někomu poslouží.")
        wx.AboutBox(info)
        
    def OVypoctu(self,e):
        text = (u'Výpočetní program Imhotep bere v úvahu následující předpoklady v souladu s normou:'
                u'\n\n  1) Předpokládá styk dvou stejných přírub (tedy stejného typu a geometrie)'
                u'\n  2) Bere v úvahu pouze rovnoměrné rozložení šroubů'
                u'\n  3) Hodnota Poissonovy konstanty je pevně zvolena 0,3'
                u'\n  4) Tabulované hodnoty meze kluzu materiálu lze vybrat jen do tloušťky 150 mm a teploty 400 °C.'
                u' Pro vyšší hodnoty neproběhne výpočet'
                u'\n  5) Uživatel musí zvolit tloušťku polotovaru, ze kterého se bude vyrábět příruba,'
                u' protože právě ta rozhoduje o mechanických vlastnostech materiálu'
                u'\n  6) Plášť i příruba mají teplotu T_prov pro provoz a T_mont pro montáž,'
                u' zatímco teplota šroubů se určuje zadáním meze kluzu'
                u'\n  7) Shoduje-li se T_mont a T_prov, pak se shodují meze napětí pro oba stavy a tudíž program provede'
                u' výpočet jen pro ten stav, který má větší moment. Je-li montážní moment větší, tak dojde ke zbarvení nadpisu'
                u'\n  8) Předpokládá se uživatelova schopnost zadat smysluplnou geometrii - program nehlídá logické kolize rozměrů'
                u' jako například, že roztečná kružnice šroubů musí být větší než světlost příruby'
                u'\n  9) Zbytek výpočtu je kompletně v souladu s textem normy ČSN EN 13445-3. Její nastudování je žádoucí'
                u'\n  10) Při volbě těsnění a šroubů doporučuji vzít v úvahu tabulku 11.4-1 a 11.4-2')
        
        okno = wx.Dialog(self,-1,u'Předpoklady výpočtu',size=(400,485))
        okno.Centre()
        
        wx.StaticText(okno,-1,text,pos=(10,10))
        okno.Show()

    def Hlaseni(self,zprava,nadpis):
        u"""Hezká přímočará funkce, kde zavoláním dostanu výpisové okno"""
        import wx.lib.agw.genericmessagedialog as jou
        dlg = jou.GenericMessageDialog(None, zprava, nadpis, agwStyle=wx.ICON_INFORMATION|wx.OK)
        dlg.ShowModal()
        dlg.Destroy()


class Uvod(wx.Dialog):
    u'''
    Úvodní okno k programu, kde oznamovací okno představí program a vyzve k zadání typu příruby 
    '''
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, -1, u'Zvolte typ příruby', size=(835,658), 
                          style = wx.SYSTEM_MENU| wx.CLOSE_BOX|wx.CAPTION)
        self.CentreOnScreen()
        
        self.typ = None
        
        # Hezké okno, krátký a efektivní kod :-)        
        import wx.lib.agw.genericmessagedialog as GMD
        main_message = (u"Právě jste zapli program pro pevnostní výpočet přírub dle normy ČSN EN 13445-3."
        u"\nVeškeré značení je v souladu s touto normou"
        u"\n\nZačněte volbou typu geometrie příruby kliknutím na obrázek")
        dlg = GMD.GenericMessageDialog(None, main_message, u"Vstup do programu Imhotep",
                                    agwStyle=wx.ICON_INFORMATION|wx.OK)
        dlg.ShowModal()
        dlg.Destroy()
        
        # Nahraje obrázky
        typI = wx.Bitmap('typ_i.jpg')
        typI = self.scale_bitmap(typI, 400, 300)
        typII = wx.Bitmap('typ_ii.jpg')
        typII = self.scale_bitmap(typII, 400, 300)
        typIII = wx.Bitmap('typ_iii.jpg')
        typIII = self.scale_bitmap(typIII, 400, 300)

        # vykreslí obrázky
        mezera = 10
        typ_I = wx.StaticBitmap(self, -1, typI, (mezera,mezera))
        pos1 = typI.GetWidth() + mezera + mezera
        typ_II = wx.StaticBitmap(self, -1, typII, (pos1,mezera))
        pos2 = typI.GetHeight() + mezera + mezera
        typ_III = wx.StaticBitmap(self, -1, typIII, (mezera,pos2))
        
        # Klikání na obrázky
        typ_I.Bind(wx.EVT_LEFT_DOWN, self.Pocitat)
        typ_II.Bind(wx.EVT_LEFT_DOWN, self.Pocitat)
        typ_III.Bind(wx.EVT_LEFT_DOWN, self.Pocitat)
        
        self.typy = ((typ_I, 1),
                     (typ_II, 2),
                     (typ_III, 3))
        
        self.Show()
         
    
    def Pocitat(self,e):
        # hezka funkce pro ukonceni, neaktivni, ale chci ji uchovat
        # p = wx.GetTopLevelParent(self) 
        # if p:
        #     p.Close()
        obrazky, cisla = zip(*self.typy)
        indexObr = obrazky.index(e.GetEventObject())
        self.typ = cisla[indexObr]
        self.Close(True)
        
    def scale_bitmap(self, bitmap, width, height):
        # Fce, která umožňuje určit velikost obrázku, další možnost je přes sizery
        image = wx.ImageFromBitmap(bitmap)
        image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
        result = wx.BitmapFromImage(image)
        return result
   
        
class VystupniOkno(wx.Dialog):
    u'''Vykreslí výstupní okno'''

    def __init__(self, parent,vstup):
        if vstup['T_prov'] == vstup['T_mont']: # Šířka výpisu bude dvojnásobná pro různé teploty
            rozmer =(410,740)
        else:
            rozmer = (820,740)
        wx.Dialog.__init__(self, parent, -1, u'Výsledky', size=rozmer, 
                        style = wx.SYSTEM_MENU| wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.CAPTION)
        self.Centre(True)
        self.panel = panel = wx.Panel(self,pos=(10,10))
        
        # Společný nadpis
        sloupec = wx.BoxSizer(wx.VERTICAL)
        radek = wx.BoxSizer(wx.HORIZONTAL)
        radek.Add(self.Raadek('                  P =',round(vstup['P'],2)),1,flag=wx.ALIGN_RIGHT)
        radek.Add(self.Raadek('                T_prov =',round(vstup['T_prov'],2)),1,flag=wx.ALIGN_RIGHT)
        radek.Add(self.Raadek('                T_mont =',round(vstup['T_mont'],2)),1,flag=wx.ALIGN_RIGHT)
        mezera = wx.StaticText(panel,-1,'----------------------------------------------------------------------------------'
                               '----------------------------------------------------------------------------------')
        sloupec.Add(mezera,1)
        sloupec.Add(radek,1)
        mezera = wx.StaticText(panel,-1,'----------------------------------------------------------------------------------'
                               '----------------------------------------------------------------------------------')
        sloupec.Add(mezera,1)
        
        # Podmínka pro šrouby - nezávisí na teplotě
        nadpis = wx.StaticText(panel,-1,u'  Kritérium průřezu šroubů dle 11.5.2:')
        font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
        font.SetUnderlined(True)
        nadpis.SetFont(font)
        krit = wx.StaticText(panel,-1,'  A_B >= A_Bmin')
        sloupec.Add(nadpis,1)
        sloupec.Add(krit,1)
        
        if vstup['A_B'] >= vstup['A_Bmin']:
            vysl = wx.StaticText(panel,-1,u'        SPLNĚNO')
            vysl.SetForegroundColour('green')
            sloupec.Add(vysl,1)
        else:
            vysl = wx.StaticText(panel,-1,u'        NESPLNĚNO')
            vysl.SetForegroundColour('red')
            sloupec.Add(vysl,1)
          
        # Příprava slovníku pro provozní podmínky
        prov = {'sigmaH':vstup['sigmaH_prov'],
                'sigmaHmax':vstup['sigmaHmax_prov'],
                'sigmaR':vstup['sigmaR_prov'],
                'sigmaRmax':vstup['sigmaRmax_prov'],
                'sigmaTangenc':vstup['sigmaTangenc_prov'],
                'sigmaHplusR':vstup['sigmaHplusR_prov'],
                'Re_prir':vstup['Re_prirProv']
                }
        
        # Přiřazení sloupců, liší-li se teploty
        if vstup['T_prov'] == vstup['T_mont']: # Zde jen jeden výpis
            if vstup['typ'] == 2 or vstup['typ'] == 3:
                prov['Re_plast'] = vstup['Re_plastProv'] # Přidat plášť pro dané typy
            
            # Dle momentu určíme, který stav je extrémní
            if vstup['M_op'] >= vstup['M_A']:
                text = u' NAPĚTÍ PRO PROVOZNÍ STAV'
            else:
                text = u' POZOR!! ZOBRAZENO NAPĚTÍ PRO MONTÁŽNÍ STAV'
                
            sizer = self.Vykresleni(vstup,prov,text)
        else: # Pro různé teploty nutné 2 výpisy
            mont = {'sigmaH':vstup['sigmaH_mont'],  # Slovník pro montážní podmínky
                'sigmaHmax':vstup['sigmaHmax_mont'],
                'sigmaR':vstup['sigmaR_mont'],
                'sigmaRmax':vstup['sigmaRmax_mont'],
                'sigmaTangenc':vstup['sigmaTangenc_mont'],
                'sigmaHplusR':vstup['sigmaHplusR_mont'],
                'Re_prir':vstup['Re_prirMont']
                }
            if vstup['typ'] == 2 or vstup['typ'] == 3: # Vyjímka pro plášť
                mont['Re_plast'] = vstup['Re_plastMont']
                prov['Re_plast'] = vstup['Re_plastProv']
        
            montText = u' NAPĚTÍ PRO MONTÁŽNÍ STAV'
            provText = u' NAPĚTÍ PRO PROVOZNÍ STAV'
            sizer = wx.BoxSizer(wx.HORIZONTAL) # Výpisy srovnáme vedle sebe do horizontálního sizeru
            mont = self.Vykresleni(vstup,mont,montText)
            prov = self.Vykresleni(vstup,prov,provText)
            sizer.Add(mont,1)
            sizer.Add(prov,1)
        
        mezera = wx.StaticText(panel,-1,'----------------------------------------------------------------------------------'
                               '----------------------------------------------------------------------------------')
        sloupec.Add(mezera,1)
        F = vstup['W']/vstup['n']
        sloupec.Add(self.Raadek(u'  Předpětí ve šroubu W/n =',round(F,2)),1)
        sloupec.Add(self.Raadek(u'  Průřez šroubů A_B =',round(vstup['A_B'],2)),1)
        sloupec.Add(self.Raadek(u'  Minimální průřez šroubů A_Bmin =',round(vstup['A_Bmin'],2)),1)
            
        # Dokončení a aktivování sizerů
        sloupec.Add(sizer,1)    
        panel.SetSizer(sloupec)
        self.Show()
        
        
    def Vykresleni(self,vstup,spesl,text):
        u'''Fce vrátí sizer se zobrazenými veličinami napětí pro daný stav'''
        panel = self.panel
        sloupec = wx.BoxSizer(wx.VERTICAL)
            
        # Nadpis určující o který stav jde
        mezera = wx.StaticText(panel,-1,'----------------------------------------------------------------------------------')
        sloupec.Add(mezera,1)
        nadpis = wx.StaticText(panel,-1,text)
        # Podmínka, která způsobí, že při rovnosti teplot a větším montážním momentu se nadpis zbarví do oranžova
        if (vstup['M_op'] < vstup['M_A']) and (vstup['T_prov'] == vstup['T_mont']): 
            nadpis.SetForegroundColour('orange')
        font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL) # Znovu musím nadefinovat font nadpisu
        font.SetUnderlined(True)
        nadpis.SetFont(font)
        sloupec.Add(nadpis,1)
        
        # Podmínky pro napětí
        mezera = wx.StaticText(panel,-1,'----------------------------------------------------------------------------------')
        sloupec.Add(mezera,1)
        nadpis = wx.StaticText(panel,-1,u'  Kritéria pro napětí dle 11.5.4.2:')
        nadpis.SetFont(font)
        sloupec.Add(nadpis,1)
        krit = wx.StaticText(panel,-1,u'  k*sigma_H <= 1,5*min(f,f_H)')
        sloupec.Add(krit,1)
        if abs(spesl['sigmaH']) <= spesl['sigmaHmax']:
            vysl = wx.StaticText(panel,-1,u'        SPLNĚNO') 
            vysl.SetForegroundColour('green')
            sloupec.Add(vysl,1)
        else:
            vysl = wx.StaticText(panel,-1,u'        NESPLNĚNO') 
            vysl.SetForegroundColour('red')
            sloupec.Add(vysl,1)
        # 2    
        krit = wx.StaticText(panel,-1,u'  k*sigma_R <= f')
        sloupec.Add(krit,1)
        if abs(spesl['sigmaR']) <= spesl['sigmaRmax']:
            vysl = wx.StaticText(panel,-1,u'        SPLNĚNO') 
            vysl.SetForegroundColour('green')
            sloupec.Add(vysl,1)
        else:
            vysl = wx.StaticText(panel,-1,u'        NESPLNĚNO') 
            vysl.SetForegroundColour('red')
            sloupec.Add(vysl,1)
        # 3    
        krit = wx.StaticText(panel,-1,u'  k*sigma_Tangenc <= f')
        sloupec.Add(krit,1)
        if abs(spesl['sigmaTangenc']) <= spesl['sigmaRmax']:
            vysl = wx.StaticText(panel,-1,u'        SPLNĚNO')
            vysl.SetForegroundColour('green')
            sloupec.Add(vysl,1)
        else:
            vysl = wx.StaticText(panel,-1,u'        NESPLNĚNO')
            vysl.SetForegroundColour('red')
            sloupec.Add(vysl,1)
        # 4    
        krit = wx.StaticText(panel,-1,u'  0,5*k*(sigma_H + sigma_R) <= f')
        sloupec.Add(krit,1)
        if abs(spesl['sigmaH']+spesl['sigmaR']) <= spesl['sigmaHplusR']:
            vysl = wx.StaticText(panel,-1,u'        SPLNĚNO') 
            vysl.SetForegroundColour('green')
            sloupec.Add(vysl,1)
        else:
            vysl = wx.StaticText(panel,-1,u'        NESPLNĚNO')
            vysl.SetForegroundColour('red')
            sloupec.Add(vysl,1)
        # 5    
        krit = wx.StaticText(panel,-1,u'  0,5*k*(sigma_H + sigma_Tangenc) <= f')
        sloupec.Add(krit,1)
        if abs(spesl['sigmaH']+spesl['sigmaTangenc']) <= spesl['sigmaHplusR']:
            vysl = wx.StaticText(panel,-1,u'        SPLNĚNO')
            vysl.SetForegroundColour('green')
            sloupec.Add(vysl,1)
        else:
            vysl = wx.StaticText(panel,-1,u'        NESPLNĚNO')
            vysl.SetForegroundColour('red')
            sloupec.Add(vysl,1)
        
        # Výpis hodnot
        mezera = wx.StaticText(panel,-1,'----------------------------------------------------------------------------------')
        sloupec.Add(mezera,1)
        nadpis = wx.StaticText(panel,-1,u'  Spočtené veličiny:')
        nadpis.SetFont(font)
        sloupec.Add(nadpis,1)
        
        sloupec.Add(self.Raadek('  sigma_R =',round(spesl['sigmaR'],2)),1)
        sloupec.Add(self.Raadek('  sigma_H =',round(spesl['sigmaH'],2)),1)
        sloupec.Add(self.Raadek('  sigma_Tangenc =',round(spesl['sigmaTangenc'],2)),1)
        sloupec.Add(self.Raadek('  sigma_H + sigma_Tangenc =',round(spesl['sigmaTangenc']+spesl['sigmaH'],2)),1)
        sloupec.Add(self.Raadek('  sigma_H + sigma_R =',round(spesl['sigmaR']+spesl['sigmaH'],2)),1)
        sloupec.Add(self.Raadek('  sigma_Rmax = sigma_TangencMax =',round(spesl['sigmaRmax'],2)),1)
        sloupec.Add(self.Raadek('  sigma_Hmax =',round(spesl['sigmaHmax'],2)),1)
        sloupec.Add(self.Raadek('  sigma_HplusRmax =',round(spesl['sigmaHplusR'],2)),1)
        sloupec.Add(self.Raadek('  sigma_HplusTangencMax =',round(spesl['sigmaHplusR'],2)),1)
        sloupec.Add(self.Raadek(u'  R_e příruby =',round(spesl['Re_prir'],2)),1)
        #sloupec.Add(self.Raadek(u'  Rm příruby =',round(vstup['Rm_prir'],2)),1) # Mez pevnosti jsem zatím oddělal
        if vstup['typ'] != 1:
            sloupec.Add(self.Raadek(u'  R_e pláště =',round(spesl['Re_plast'],2)),1)
            #sloupec.Add(self.Raadek(u'  R_m pláště =',round(vstup['Rm_plast'],2)),1)
        
        return sloupec
        
        
    def Raadek(self,text,vystup):
        u'''Fce vrátí řádkový sizer obsahující text a vstup s textem'''
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        
        a = wx.StaticText(self.panel,-1,text)
        c = str(vystup)
        b = wx.TextCtrl(self.panel,-1,c)
        sizer.Add(a,1)
        sizer.Add(b,1)
        
        return sizer
    
    
app = wx.App(False)
frame = Bakala(None)
app.MainLoop()