#   Programmer: Daniel Pozmanter
#   E-mail:     drpython@bluebottle.com
#   Note:       You must reply to the verification e-mail to get through.
#
#   Copyright 2003-2004 Daniel Pozmanter
#
#   Distributed under the terms of the GPL (GNU Public License)
#
#    DrPython is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#Plugin
#Find All
#Version: 0.1.1, 04.04.2007:
#Updated for DrPython 1.65 and wxPython 2.8

import wx, wx.lib.dialogs
import os.path, re
import drFindReplaceDialog
import drPrefsFile

def OnAbout(DrFrame):
  AboutString = """Find All:

Version: 0.1.1

By Daniel Pozmanter
changes for version 0.0.9 by Franz Steinhaeusler (07/14/2005).
changes for version 0.1.0 by Franz Steinhaeusler (02/19/2007).
  (update to run with wxPython 2.8)
changes for version 0.1.1 by AB :shows entire line (03 April 2007)
Released under the GPL.

Credits:

Franz Steinhausler: Bug-Report With Fix."""
  d = wx.lib.dialogs.ScrolledMessageDialog(DrFrame, AboutString, "About")
  d.ShowModal()
  d.Destroy()

class drFindAllDialog(drFindReplaceDialog.drFindReplaceDialog):
  def __init__(self, parent, id, title):
    drFindReplaceDialog.drFindReplaceDialog.__init__(self, parent, id, title, parent.GetActiveSTC())

    self.txtSearchFor.SetHistory(parent.FindAllHistory)

    self.chkFindBackwards.Enable(False)
    self.chkFromCursor.Enable(False)

  def OnbtnFind(self, event):
    self.Show(0)
    text = self.stc.GetText()
    findtext = self.txtSearchFor.GetText()

    self.txtSearchFor.AppendToHistory(self.parent.FindAllHistory)

    findflags = 0
    if self.chkWholeWord.GetValue():
      findflags = findflags | wx.stc.STC_FIND_WHOLEWORD
    if self.chkMatchCase.GetValue():
      findflags = findflags | wx.stc.STC_FIND_MATCHCASE

    try:
      x = self.stc.FindAll
    except:
      self.stc.FindAll = None

    if not (self.stc.FindAll):
      target, i = self.parent.mainpanel.GetTargetNotebookPage(self.parent.FindAllPanelPositon, "FindAll")
      self.stc.FindAll = FindAllPanel(target, -1, self.parent.FindAllPanelPositon, self.stc)
      self.stc.FindAll.Index = i
      self.parent.currentpage.OnSize(None)
      target.SetPanel(self.stc.FindAll)
      self.parent.mainpanel.ShowPanel(self.stc.FindAll.position, self.stc.FindAll.Index, True)

    if self.stc.FindAll.boxResults.GetCount() > 0:
      self.stc.FindAll.boxResults.Clear()
      self.stc.FindAll.ClrOldResults()

    if self.chkRegularExpression.GetValue():
      case = 0
      if not matchcase:
        case = re.IGNORECASE

      finder = re.compile(findtext, case | re.MULTILINE)
      y = finder.search(text)
      if y is not None:
        if y.group():
          t = re.finditer(finder, text)
          try:
            item = t.next()
          except:
            item = None
          results = []
          items = []
          while item is not None:
            if item.group():
              self.stc.FindAll.AppendResult(self.stc.LineFromPosition(item.start()), item.group())
            try:
              item = t.next()
            except:
              item = None
    else:
      endpos = self.stc.GetLength()
    
      l = len(findtext)
      i = self.stc.FindText(0, endpos, findtext, findflags)
      last = 0
      while i > -1:
        #self.stc.FindAll.AppendResult(i, text[i:i+l])
        line=self.stc.LineFromPosition(i)
        buff=self.stc.GetLineRaw(line).strip()
        self.stc.FindAll.AppendResult(i, buff)
        last = i + 1
        i = self.stc.FindText(last, endpos, findtext, findflags)

    self.parent.FindOptions = self.GetOptions()

class FindAllPanel(wx.Panel):
  def __init__(self, parent, id, position, stc):
    wx.Panel.__init__(self, parent, id)

    self.stc = stc

    self.ID_RESULTS = 11001
    self.ID_CLOSE = 11002

    self.ClrOldResults()

    self.theSizer = wx.BoxSizer(wx.VERTICAL)

    self.boxResults = wx.ListBox(self, self.ID_RESULTS, wx.DefaultPosition, wx.Size(200, 200))
    self.theSizer.Add(self.boxResults, 9, wx.EXPAND)

    self.bSizer = wx.BoxSizer(wx.HORIZONTAL)
    self.btnClose = wx.Button(self, self.ID_CLOSE, "&Close")
    self.bSizer.Add(self.btnClose, 0,  wx.SHAPED | wx.ALIGN_RIGHT)

    self.theSizer.Add(self.bSizer, 0, wx.EXPAND)

    self.position = position

    self.parent = parent

    #confusing

    #parent = drSidePanel
    #parent.GetParent() = drSidePanelNotebook
    #parent.GetParent().GetParent() = drSashWindow
    #parent.GetParent().GetParent().GetParent() = drMainPanel
    #parent.GetParent().GetParent().GetParent().GetParent() = drFrame

    #drMainPanel
    self.panelparent = parent.GetGrandParent().GetParent()
    self.drframe = self.panelparent.GetParent()
    #self.grandparent = parent.GetGrandParent().GetGrandParent().GetParent()
    #returns None

    self.SetAutoLayout(True)
    self.SetSizer(self.theSizer)

    self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=self.ID_CLOSE)
    self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnResult, id=self.ID_RESULTS)

  def ClrOldResults(self):
    self.Lines = []
    self.Positions = []
    self.Results = []

  def AppendResult(self, pos, text):
    line = self.stc.LineFromPosition(pos)
    self.Positions.append(pos)
    self.Lines.append(line)
    self.Results.append(text)
    self.boxResults.Append(str(line+1) + ": " + text)

  def OnbtnClose(self, event):
    self.stc.FindAll = None
    self.panelparent.ClosePanel(self.position, self.Index)

  def OnResult(self, event):
    sel = self.boxResults.GetSelection()
    if sel > -1:
      if self.drframe.prefs.docfolding:
        self.stc.EnsureVisible(self.Lines[sel])
      self.stc.ScrollToLine(self.Lines[sel])
      self.stc.GotoLine(self.Lines[sel])
      self.stc.SetSelection(self.Positions[sel], self.Positions[sel]+len(self.Results[sel]))

def OnPreferences(DrFrame):
  d = wx.SingleChoiceDialog(DrFrame, "Select default position:", "Preferences: Find All", ["Left Panel", "Right Panel", "Top Panel", "Bottom Panel"], wx.CHOICEDLG_STYLE)
  d.SetSize(wx.Size(250, 250))
  if d.ShowModal() == wx.ID_OK:
    DrFrame.CodemarksPanelPositon = d.GetSelection()
    f = file(DrFrame.pluginspreferencesdirectory + "/FindAll.preferences.dat", 'w')
    f.write("<findall.position>" + str(DrFrame.FindAllPanelPositon) + "</findall.position>")
    f.close()
  d.Destroy()

def Plugin(DrFrame):
  DrFrame.FindAll = None

  DrFrame.FindAllHistory = []

  #Preferences
  #0 = Right, 1 = Left
  DrFrame.FindAllPanelPositon = 0

  if os.path.exists(DrFrame.pluginspreferencesdirectory + "/FindAll.preferences.dat"):
    f = file(DrFrame.pluginspreferencesdirectory + "/FindAll.preferences.dat", 'r')
    text = f.read()
    f.close()
    DrFrame.FindAllPanelPositon = drPrefsFile.GetPrefFromText(DrFrame.FindAllPanelPositon, text, "findall.position", True)

  #End Preferences

  def OnFindAll(event):
    d = drFindAllDialog(DrFrame, -1, "Find All")
    d.SetOptions(DrFrame.FindOptions)
    d.Show(True)

  ID_FIND_ALL = DrFrame.GetNewId()

  DrFrame.LoadPluginShortcuts('FindAll')

  DrFrame.searchmenu.AppendSeparator()
  DrFrame.searchmenu.Append(ID_FIND_ALL, "Find All")

  DrFrame.Bind(wx.EVT_MENU, OnFindAll, id=ID_FIND_ALL)

  DrFrame.AddPluginFunction("FindAll", "Find All", OnFindAll)
