// Text File Viewer
//
// Aufruf: viewer
//
// Klaus Kusche, 2011

#include <wx/app.h>
#include <wx/frame.h>
#include <wx/splitter.h> 
#include <wx/textctrl.h> 
#include <wx/dirctrl.h> 
#include <wx/button.h> 
#include <wx/sizer.h> 
#include <wx/event.h>

class MyApp: public wxApp
{
  virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)

class MyFrame: public wxFrame
{
  public:
    MyFrame(const wxString &title);

    void OnSel(wxTreeEvent &event);
    // vier neue Event-Funktionen (für jeden Button eine)
    void OnQuit(wxCommandEvent &event);
    void OnLeft(wxCommandEvent &event);
    void OnRight(wxCommandEvent &event);
    void OnBoth(wxCommandEvent &event);
        
  private:
    wxSplitterWindow *Splitter;
    wxGenericDirCtrl *Tree;
    wxTextCtrl *Text;
};

// Nummern für die Buttons zur Unterscheidung ihrer Klick-Events
enum
{
  ID_Quit = 1,
  ID_Left,
  ID_Right,
  ID_Both
};

bool MyApp::OnInit()
{
  MyFrame *frame = new MyFrame("File Viewer");
  frame->Show(true);
  SetTopWindow(frame);
  return true;
} 

MyFrame::MyFrame(const wxString &title)
: wxFrame(nullptr, -1, title),
  Splitter(new wxSplitterWindow(this, -1)),
  Tree(new wxGenericDirCtrl(Splitter, -1)),
  Text(new wxTextCtrl(Splitter, -1, "",
       wxDefaultPosition, wxDefaultSize, 
       wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP | wxTE_PROCESS_TAB))    
{
  // neue Buttons und Sizer anlegen
  // da wir sie in den Event-Methoden nicht brauchen,
  // reichen dafür lokale Variablen (Member sind auch ok, aber unnötig)
  // das "&" in der Button-Beschriftung markiert den Shortkey
  wxButton *Quit = new wxButton(this, ID_Quit, "E&xit");
  wxButton *Left = new wxButton(this, ID_Left, "&Left side");
  wxButton *Right = new wxButton(this, ID_Right, "&Right side");
  wxButton *Both = new wxButton(this, ID_Both, "&Both sides");
  // das Argument (eine int-Konstante) gibt die "Stapelrichtung" an
  wxBoxSizer *mainsizer = new wxBoxSizer(wxVERTICAL);
  wxBoxSizer *buttonsizer = new wxBoxSizer(wxHORIZONTAL);

  // 1. Arg: Objekt
  // 2. Arg: Proportionaler Anteil an der Größe (0: wächst nicht mit)
  // 3. Arg: Optionen.
  // wxALL: Rundherum Rand lassen (wxTOP: nur oben)
  // wxEXPAND: In beide Richtungen den vorhandenen Platz ausfüllen
  // 4. Arg: Randbreite in Pixel
  buttonsizer->Add(Left, 1, wxALL | wxEXPAND, 5);    
  buttonsizer->Add(Both, 1, wxALL | wxEXPAND, 5);    
  buttonsizer->Add(Right, 1, wxALL | wxEXPAND, 5);    
  buttonsizer->Add(Quit, 1, wxALL | wxEXPAND, 5);    
  mainsizer->Add(Splitter, 1, wxTOP | wxEXPAND, 5);
  mainsizer->Add(buttonsizer, 0, wxEXPAND);
  mainsizer->SetMinSize(800, 600);  // minimale Größe festlegen
  // "mainsizer ist der Sizer des Hauptfensters":
  // Größen von Fenster und mainsizer koppeln
  SetSizerAndFit(mainsizer);
  
  Splitter->SetMinimumPaneSize(20);
  Splitter->SplitVertically(Tree, Text, 250);
  
  Tree->SetPath(wxGetCwd());

  Bind(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, &MyFrame::OnSel, this);
  Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnQuit, this, ID_Quit);
  Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnLeft, this, ID_Left);
  Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnRight, this, ID_Right);
  Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnBoth, this, ID_Both);
}

// Wird aufgerufen wenn Exit-Button gedrückt wurde
void MyFrame::OnQuit(wxCommandEvent &WXUNUSED(event))
{
  Close(true);  // Hauptfenster schließen
}

// Umschalten der Ansicht
void MyFrame::OnLeft(wxCommandEvent &WXUNUSED(event))
{
  if (Splitter->IsSplit()) 
    Splitter->Unsplit(Text);
  else if (Splitter->GetWindow1() == Text) {
    Splitter->ReplaceWindow(Text,Tree);
    Text->Hide();
    Tree->Show();
  }
}

void MyFrame::OnRight(wxCommandEvent &WXUNUSED(event))
{
  if (Splitter->IsSplit()) 
    Splitter->Unsplit(Tree);
  else if (Splitter->GetWindow1() == Tree) {
    Splitter->ReplaceWindow(Tree,Text);
    Tree->Hide();
    Text->Show();
  }
}

void MyFrame::OnBoth(wxCommandEvent &WXUNUSED(event))
{
  if (!Splitter->IsSplit()) {
    Splitter->SplitVertically(Tree, Text, 250);
    Tree->Show();
    Text->Show();
  }
}

void MyFrame::OnSel(wxTreeEvent &WXUNUSED(event))
{
  wxString name = Tree->GetFilePath();
  if (name.Len() != 0) {
    Text->LoadFile(name);
  }
}
