/* * The copyright in this software is being made available under the 2-clauses * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita'  degli studi di Perugia (UPG), Italy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "OPJViewer.h" ///////////////////////////////////////////////////////////////////// // Encoding thread class ///////////////////////////////////////////////////////////////////// OPJEncoThread::OPJEncoThread(OPJCanvas *canvas) : wxThread() { m_count = 0; m_canvas = canvas; } void OPJEncoThread::WriteText(const wxString& text) { wxString msg; // before doing any GUI calls we must ensure that this thread is the only // one doing it! #ifndef __WXGTK__ wxMutexGuiEnter(); #endif // __WXGTK__ msg << text; m_canvas->WriteText(msg); #ifndef __WXGTK__ wxMutexGuiLeave(); #endif // __WXGTK__ } void OPJEncoThread::OnExit() { wxCriticalSectionLocker locker(wxGetApp().m_enco_critsect); wxArrayThread& ethreads = wxGetApp().m_enco_threads; ethreads.Remove(this); if (ethreads.IsEmpty() ) { // signal the main thread that there are no more threads left if it is // waiting for us if (wxGetApp().m_enco_waitingUntilAllDone) { wxGetApp().m_enco_waitingUntilAllDone = false; wxGetApp().m_enco_semAllDone.Post(); } } } void *OPJEncoThread::Entry() { wxString text; srand(GetId()); //int m_countnum = rand() % 9; //text.Printf(wxT("Deco thread 0x%lx started (priority = %u, time = %d)."), // GetId(), GetPriority(), m_countnum); text.Printf(wxT("Enco thread %d started"), m_canvas->m_childframe->m_winnumber); WriteText(text); // set handler properties wxJPEG2000Handler *jpeg2000handler = (wxJPEG2000Handler *) wxImage::FindHandler(wxBITMAP_TYPE_JPEG2000); jpeg2000handler->m_subsampling = wxGetApp().m_subsampling; jpeg2000handler->m_origin = wxGetApp().m_origin; jpeg2000handler->m_rates = wxGetApp().m_rates; jpeg2000handler->m_quality = wxGetApp().m_quality; jpeg2000handler->m_enablequality = wxGetApp().m_enablequality; jpeg2000handler->m_multicomp = wxGetApp().m_multicomp; jpeg2000handler->m_irreversible = wxGetApp().m_irreversible; jpeg2000handler->m_resolutions = wxGetApp().m_resolutions; jpeg2000handler->m_progression = wxGetApp().m_progression; jpeg2000handler->m_cbsize = wxGetApp().m_cbsize; jpeg2000handler->m_prsize = wxGetApp().m_prsize; jpeg2000handler->m_tsize = wxGetApp().m_tsize; jpeg2000handler->m_torigin = wxGetApp().m_torigin; jpeg2000handler->m_enablesop = wxGetApp().m_enablesop; jpeg2000handler->m_enableeph = wxGetApp().m_enableeph; jpeg2000handler->m_enablebypass = wxGetApp().m_enablebypass; jpeg2000handler->m_enablerestart = wxGetApp().m_enablerestart; jpeg2000handler->m_enablereset = wxGetApp().m_enablereset; jpeg2000handler->m_enablesegmark = wxGetApp().m_enablesegmark; jpeg2000handler->m_enableerterm = wxGetApp().m_enableerterm; jpeg2000handler->m_enablevsc = wxGetApp().m_enablevsc; jpeg2000handler->m_enableidx = wxGetApp().m_enableidx; jpeg2000handler->m_index = m_canvas->m_savename.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxGetApp().m_index; jpeg2000handler->m_enablecomm = wxGetApp().m_enablecomm; jpeg2000handler->m_comment = wxGetApp().m_comment; jpeg2000handler->m_enablepoc = wxGetApp().m_enablepoc; jpeg2000handler->m_poc = wxGetApp().m_poc; // save the file if (!m_canvas->m_image100.SaveFile(m_canvas->m_savename.GetFullPath(), (wxBitmapType) wxBITMAP_TYPE_JPEG2000)) { WriteText(wxT("Can't save image")); return NULL; } text.Printf(wxT("Enco thread %d finished"), m_canvas->m_childframe->m_winnumber); WriteText(text); return NULL; } ///////////////////////////////////////////////////////////////////// // Decoding thread class ///////////////////////////////////////////////////////////////////// OPJDecoThread::OPJDecoThread(OPJCanvas *canvas) : wxThread() { m_count = 0; m_canvas = canvas; } void OPJDecoThread::WriteText(const wxString& text) { wxString msg; // we use a fake event and post it for inter-thread gui communication wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, OPJFRAME_THREADLOGMSG); event.SetInt(-1); msg << text; event.SetString(msg); wxPostEvent(this->m_canvas->m_childframe->m_frame, event); /* // before doing any GUI calls we must ensure that this thread is the only // one doing it! #ifndef __WXGTK__ wxMutexGuiEnter(); #endif // __WXGTK__ msg << text; m_canvas->WriteText(msg); #ifndef __WXGTK__ wxMutexGuiLeave(); #endif // __WXGTK__ */ } void OPJDecoThread::OnExit() { wxCriticalSectionLocker locker(wxGetApp().m_deco_critsect); wxArrayThread& dthreads = wxGetApp().m_deco_threads; dthreads.Remove(this); if (dthreads.IsEmpty() ) { // signal the main thread that there are no more threads left if it is // waiting for us if (wxGetApp().m_deco_waitingUntilAllDone) { wxGetApp().m_deco_waitingUntilAllDone = false; wxGetApp().m_deco_semAllDone.Post(); } } } void *OPJDecoThread::Entry() { wxString text; //srand(GetId()); //int m_countnum = rand() % 9; //text.Printf(wxT("Deco thread 0x%lx started (priority = %u, time = %d)."), // GetId(), GetPriority(), m_countnum); // we have started text.Printf(wxT("Deco thread %d started"), m_canvas->m_childframe->m_winnumber); WriteText(text); // prepare dummy wximage wxBitmap bitmap(100, 100); wxImage image(100, 100, true); //= bitmap.ConvertToImage(); image.Destroy(); // show image full name WriteText(m_canvas->m_fname.GetFullPath()); // set handler properties wxJPEG2000Handler *jpeg2000handler = (wxJPEG2000Handler *) wxImage::FindHandler(wxBITMAP_TYPE_JPEG2000); jpeg2000handler->m_reducefactor = wxGetApp().m_reducefactor; jpeg2000handler->m_qualitylayers = wxGetApp().m_qualitylayers; jpeg2000handler->m_components = wxGetApp().m_components; jpeg2000handler->m_framenum = wxGetApp().m_framenum; #ifdef USE_JPWL jpeg2000handler->m_enablejpwl = wxGetApp().m_enablejpwl; jpeg2000handler->m_expcomps = wxGetApp().m_expcomps; jpeg2000handler->m_maxtiles = wxGetApp().m_maxtiles; #endif // USE_JPWL #ifdef USE_MXF wxMXFHandler *mxfffhandler = (wxMXFHandler *) wxImage::FindHandler(wxBITMAP_TYPE_MXF); mxfffhandler->m_reducefactor = wxGetApp().m_reducefactor; mxfffhandler->m_qualitylayers = wxGetApp().m_qualitylayers; mxfffhandler->m_components = wxGetApp().m_components; mxfffhandler->m_framenum = wxGetApp().m_framenum; mxfffhandler->m_filename = m_canvas->m_fname; #ifdef USE_JPWL mxfffhandler->m_enablejpwl = wxGetApp().m_enablejpwl; mxfffhandler->m_expcomps = wxGetApp().m_expcomps; mxfffhandler->m_maxtiles = wxGetApp().m_maxtiles; #endif // USE_JPWL #endif // USE_MXF // if decoding is enabled... if (wxGetApp().m_enabledeco) { // load the file if (!image.LoadFile(m_canvas->m_fname.GetFullPath(), wxBITMAP_TYPE_ANY, 0)) { WriteText(wxT("Can't load image!")); return NULL; } } else { // display a warning if (!image.Create(300, 5, false)) { WriteText(wxT("Can't create image!")); return NULL; } } // assign 100% image m_canvas->m_image100 = wxBitmap(image); // signal the frame to refresh the canvas wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, OPJFRAME_VIEWFIT); event.SetString(wxT("Fit me")); event.SetInt(m_canvas->m_childframe->m_winnumber); wxPostEvent(m_canvas->m_childframe->m_frame, event); // find a fit-to-width zoom /*int zooml, wzooml, hzooml; wxSize clientsize = m_canvas->GetClientSize(); wzooml = (int) floor(100.0 * (double) clientsize.GetWidth() / (double) (2 * OPJ_CANVAS_BORDER + image.GetWidth())); hzooml = (int) floor(100.0 * (double) clientsize.GetHeight() / (double) (2 * OPJ_CANVAS_BORDER + image.GetHeight())); zooml = wxMin(100, wxMin(wzooml, hzooml));*/ // fit to width #ifndef __WXGTK__ //m_canvas->m_childframe->m_frame->Rescale(zooml, m_canvas->m_childframe); #endif // __WXGTK__ //m_canvas->m_image = m_canvas->m_image100; //m_canvas->Refresh(); //m_canvas->SetScrollbars(20, 20, (int)(0.5 + (double) image.GetWidth() / 20.0), (int)(0.5 + (double) image.GetHeight() / 20.0)); //text.Printf(wxT("Deco thread 0x%lx finished."), GetId()); text.Printf(wxT("Deco thread %d finished"), m_canvas->m_childframe->m_winnumber); WriteText(text); return NULL; } ///////////////////////////////////////////////////////////////////// // Parsing thread class ///////////////////////////////////////////////////////////////////// OPJParseThread::OPJParseThread(OPJMarkerTree *tree, wxTreeItemId parentid) : wxThread() { m_count = 0; m_tree = tree; m_parentid = parentid; } void OPJParseThread::WriteText(const wxString& text) { wxString msg; // we use a fake event and post it for inter-thread gui communication wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, OPJFRAME_THREADLOGMSG); event.SetInt(-1); msg << text; event.SetString(msg); wxPostEvent(this->m_tree->m_childframe->m_frame, event); /* // before doing any GUI calls we must ensure that this thread is the only // one doing it! #ifndef __WXGTK__ wxMutexGuiEnter(); #endif // __WXGTK msg << text; m_tree->WriteText(msg); #ifndef __WXGTK__ wxMutexGuiLeave(); #endif // __WXGTK*/ } void OPJParseThread::OnExit() { wxCriticalSectionLocker locker(wxGetApp().m_parse_critsect); wxArrayThread& threads = wxGetApp().m_parse_threads; threads.Remove(this); if (threads.IsEmpty()) { // signal the main thread that there are no more threads left if it is // waiting for us if (wxGetApp().m_parse_waitingUntilAllDone) { wxGetApp().m_parse_waitingUntilAllDone = false; wxGetApp().m_parse_semAllDone.Post(); } } } void *OPJParseThread::Entry() { printf("Entering\n\n"); wxString text; srand(GetId()); int m_countnum = rand() % 9; text.Printf(wxT("Parse thread 0x%lx started (priority = %u, time = %d)."), GetId(), GetPriority(), m_countnum); WriteText(text); LoadFile(m_tree->m_fname); text.Printf(wxT("Parse thread 0x%lx finished."), GetId()); WriteText(text); //wxLogMessage(wxT("Entering\n")); //test wxLog thread safeness //wxBusyCursor wait; //wxBusyInfo wait(wxT("Decoding image ...")); /*for ( m_count = 0; m_count < m_countnum; m_count++ ) { // check if we were asked to exit if ( TestDestroy() ) break; text.Printf(wxT("[%u] Parse thread 0x%lx here."), m_count, GetId()); WriteText(text); // wxSleep() can't be called from non-GUI thread! wxThread::Sleep(10); }*/ // wxLogMessage(text); -- test wxLog thread safeness printf("Exiting\n\n"); return NULL; } /////////////////////////////////////////// // Parsing hread and related /////////////////////////////////////////// #if USE_GENERIC_TREECTRL BEGIN_EVENT_TABLE(OPJMarkerTree, wxGenericTreeCtrl) #else BEGIN_EVENT_TABLE(OPJMarkerTree, wxTreeCtrl) #endif /*EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, OPJMarkerTree::OnBeginDrag) EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, OPJMarkerTree::OnBeginRDrag) EVT_TREE_END_DRAG(TreeTest_Ctrl, OPJMarkerTree::OnEndDrag)*/ /*EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, OPJMarkerTree::OnBeginLabelEdit) EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, OPJMarkerTree::OnEndLabelEdit)*/ /*EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, OPJMarkerTree::OnDeleteItem)*/ #if 0 // there are so many of those that logging them causes flicker /*EVT_TREE_GET_INFO(TreeTest_Ctrl, OPJMarkerTree::OnGetInfo)*/ #endif /*EVT_TREE_SET_INFO(TreeTest_Ctrl, OPJMarkerTree::OnSetInfo) EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, OPJMarkerTree::OnItemExpanded)*/ EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, OPJMarkerTree::OnItemExpanding) /*EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, OPJMarkerTree::OnItemCollapsed) EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, OPJMarkerTree::OnItemCollapsing)*/ EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, OPJMarkerTree::OnSelChanged) /*EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, OPJMarkerTree::OnSelChanging)*/ /*EVT_TREE_KEY_DOWN(TreeTest_Ctrl, OPJMarkerTree::OnTreeKeyDown)*/ /*EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, OPJMarkerTree::OnItemActivated)*/ // so many differents ways to handle right mouse button clicks... /*EVT_CONTEXT_MENU(OPJMarkerTree::OnContextMenu)*/ // EVT_TREE_ITEM_MENU is the preferred event for creating context menus // on a tree control, because it includes the point of the click or item, // meaning that no additional placement calculations are required. EVT_TREE_ITEM_MENU(TreeTest_Ctrl, OPJMarkerTree::OnItemMenu) /*EVT_TREE_ITEM_RIGHT_CLICK(TreeTest_Ctrl, OPJMarkerTree::OnItemRClick)*/ /*EVT_RIGHT_DOWN(OPJMarkerTree::OnRMouseDown) EVT_RIGHT_UP(OPJMarkerTree::OnRMouseUp) EVT_RIGHT_DCLICK(OPJMarkerTree::OnRMouseDClick)*/ END_EVENT_TABLE() // OPJMarkerTree implementation #if USE_GENERIC_TREECTRL IMPLEMENT_DYNAMIC_CLASS(OPJMarkerTree, wxGenericTreeCtrl) #else IMPLEMENT_DYNAMIC_CLASS(OPJMarkerTree, wxTreeCtrl) #endif OPJMarkerTree::OPJMarkerTree(wxWindow *parent, OPJChildFrame *subframe, wxFileName fname, wxString name, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxTreeCtrl(parent, id, pos, size, style) { m_reverseSort = false; m_fname = fname; m_peektextCtrl = ((OPJFrame *) (parent->GetParent()->GetParent()))->m_textCtrlbrowse; CreateImageList(); // Add some items to the tree //AddTestItemsToTree(5, 5); int image = wxGetApp().ShowImages() ? OPJMarkerTree::TreeCtrlIcon_Folder : -1; wxTreeItemId rootId = AddRoot(name, image, image, new OPJMarkerData(name)); OPJParseThread *pthread = CreateParseThread(0x00, subframe); if (pthread->Run() != wxTHREAD_NO_ERROR) wxLogMessage(wxT("Can't start parse thread!")); else wxLogMessage(wxT("New parse thread started.")); m_childframe = subframe; } void OPJMarkerTree::CreateImageList(int size) { if (size == -1) { SetImageList(NULL); return; } if (size == 0) size = m_imageSize; else m_imageSize = size; // Make an image list containing small icons wxImageList *images = new wxImageList(size, size, true); // should correspond to TreeCtrlIcon_xxx enum wxBusyCursor wait; wxIcon icons[5]; icons[0] = wxIcon(icon1_xpm); icons[1] = wxIcon(icon2_xpm); icons[2] = wxIcon(icon3_xpm); icons[3] = wxIcon(icon4_xpm); icons[4] = wxIcon(icon5_xpm); int sizeOrig = icons[0].GetWidth(); for (size_t i = 0; i < WXSIZEOF(icons); i++) { if (size == sizeOrig) { images->Add(icons[i]); } else { images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size))); } } AssignImageList(images); } #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) void OPJMarkerTree::CreateButtonsImageList(int size) { if ( size == -1 ) { SetButtonsImageList(NULL); return; } // Make an image list containing small icons wxImageList *images = new wxImageList(size, size, true); // should correspond to TreeCtrlIcon_xxx enum wxBusyCursor wait; wxIcon icons[4]; icons[0] = wxIcon(icon3_xpm); // closed icons[1] = wxIcon(icon3_xpm); // closed, selected icons[2] = wxIcon(icon5_xpm); // open icons[3] = wxIcon(icon5_xpm); // open, selected for ( size_t i = 0; i < WXSIZEOF(icons); i++ ) { int sizeOrig = icons[i].GetWidth(); if ( size == sizeOrig ) { images->Add(icons[i]); } else { images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size))); } } AssignButtonsImageList(images); #else void OPJMarkerTree::CreateButtonsImageList(int WXUNUSED(size)) { #endif } void OPJParseThread::LoadFile(wxFileName fname) { wxTreeItemId rootid; // this is the root node int image = wxGetApp().ShowImages() ? m_tree->TreeCtrlIcon_Folder : -1; if (this->m_parentid) { // leaf of a tree rootid = m_parentid; m_tree->SetItemText(rootid, wxT("Parsing...")); } else { // delete the existing tree hierarchy m_tree->DeleteAllItems(); // new tree rootid = m_tree->AddRoot(wxT("Parsing..."), image, image, new OPJMarkerData(fname.GetFullPath()) ); //m_tree->SetItemFont(rootid, *wxITALIC_FONT); m_tree->SetItemBold(rootid); } // open the file wxFile m_file(fname.GetFullPath().c_str(), wxFile::read); // parsing enabled? if (wxGetApp().m_enableparse) { // what is the extension? if ((fname.GetExt() == wxT("j2k")) || (fname.GetExt() == wxT("j2c"))) { // parse the file ParseJ2KFile(&m_file, 0, m_file.Length(), rootid); } else if ((fname.GetExt() == wxT("jp2")) || (fname.GetExt() == wxT("mj2"))) { // parse the file if (this->m_parentid) { //WriteText(wxT("Only a subsection of jp2")); OPJMarkerData *data = (OPJMarkerData *) m_tree->GetItemData(rootid); ParseJ2KFile(&m_file, data->m_start, data->m_length, rootid); m_tree->Expand(rootid); } else { // as usual ParseJP2File(&m_file, 0, m_file.Length(), rootid); } } else { // unknown extension WriteText(wxT("Unknown file format!")); } } // this is the root node if (this->m_parentid) m_tree->SetItemText(rootid, wxT("Codestream")); else //m_tree->SetItemText(rootid, wxString::Format(wxT("%s (%d B)"), fname.GetFullName(), m_file.Length())); m_tree->SetItemText(rootid, fname.GetFullName()); // close the file m_file.Close(); WriteText(wxT("Parsing finished!")); } /*int OPJMarkerTree::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2) { if ( m_reverseSort ) { // just exchange 1st and 2nd items return wxTreeCtrl::OnCompareItems(item2, item1); } else { return wxTreeCtrl::OnCompareItems(item1, item2); } }*/ /*void OPJMarkerTree::AddItemsRecursively(const wxTreeItemId& idParent, size_t numChildren, size_t depth, size_t folder) { if ( depth > 0 ) { bool hasChildren = depth > 1; wxString str; for ( size_t n = 0; n < numChildren; n++ ) { // at depth 1 elements won't have any more children if ( hasChildren ) str.Printf(wxT("%s child %u"), wxT("Folder"), unsigned(n + 1)); else str.Printf(wxT("%s child %u.%u"), wxT("File"), unsigned(folder), unsigned(n + 1)); // here we pass to AppendItem() normal and selected item images (we // suppose that selected image follows the normal one in the enum) int image, imageSel; if ( wxGetApp().ShowImages() ) { image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder; imageSel = image + 1; } else { image = imageSel = -1; } wxTreeItemId id = AppendItem(idParent, str, image, imageSel, new OPJMarkerData(str)); // and now we also set the expanded one (only for the folders) if ( hasChildren && wxGetApp().ShowImages() ) { SetItemImage(id, TreeCtrlIcon_FolderOpened, wxTreeItemIcon_Expanded); } // remember the last child for OnEnsureVisible() if ( !hasChildren && n == numChildren - 1 ) { m_lastItem = id; } AddItemsRecursively(id, numChildren, depth - 1, n + 1); } } //else: done! }*/ /*void OPJMarkerTree::AddTestItemsToTree(size_t numChildren, size_t depth) { int image = wxGetApp().ShowImages() ? OPJMarkerTree::TreeCtrlIcon_Folder : -1; wxTreeItemId rootId = AddRoot(wxT("Root"), image, image, new OPJMarkerData(wxT("Root item"))); if ( image != -1 ) { SetItemImage(rootId, TreeCtrlIcon_FolderOpened, wxTreeItemIcon_Expanded); } AddItemsRecursively(rootId, numChildren, depth, 0); // set some colours/fonts for testing SetItemFont(rootId, *wxITALIC_FONT); wxTreeItemIdValue cookie; wxTreeItemId id = GetFirstChild(rootId, cookie); SetItemTextColour(id, *wxBLUE); id = GetNextChild(rootId, cookie); id = GetNextChild(rootId, cookie); SetItemTextColour(id, *wxRED); SetItemBackgroundColour(id, *wxLIGHT_GREY); }*/ /*void OPJMarkerTree::GetItemsRecursively(const wxTreeItemId& idParent, wxTreeItemIdValue cookie) { wxTreeItemId id; if ( !cookie ) id = GetFirstChild(idParent, cookie); else id = GetNextChild(idParent, cookie); if ( !id.IsOk() ) return; wxString text = GetItemText(id); wxLogMessage(text); if (ItemHasChildren(id)) GetItemsRecursively(id); GetItemsRecursively(idParent, cookie); }*/ /*void OPJMarkerTree::DoToggleIcon(const wxTreeItemId& item) { int image = (GetItemImage(item) == TreeCtrlIcon_Folder) ? TreeCtrlIcon_File : TreeCtrlIcon_Folder; SetItemImage(item, image, wxTreeItemIcon_Normal); image = (GetItemImage(item) == TreeCtrlIcon_FolderSelected) ? TreeCtrlIcon_FileSelected : TreeCtrlIcon_FolderSelected; SetItemImage(item, image, wxTreeItemIcon_Selected); }*/ void OPJMarkerTree::LogEvent(const wxChar *name, const wxTreeEvent& event) { wxTreeItemId item = event.GetItem(); wxString text; if ( item.IsOk() ) text << wxT('"') << GetItemText(item).c_str() << wxT('"'); else text = wxT("invalid item"); wxLogMessage(wxT("%s(%s)"), name, text.c_str()); } OPJParseThread *OPJMarkerTree::CreateParseThread(wxTreeItemId parentid, OPJChildFrame *subframe) { OPJParseThread *pthread = new OPJParseThread(this, parentid); if (pthread->Create() != wxTHREAD_NO_ERROR) wxLogError(wxT("Can't create parse thread!")); wxCriticalSectionLocker enter(wxGetApp().m_parse_critsect); wxGetApp().m_parse_threads.Add(pthread); return pthread; } /*// avoid repetition #define TREE_EVENT_HANDLER(name) \ void OPJMarkerTree::name(wxTreeEvent& event) \ { \ LogEvent(_T(#name), event); \ SetLastItem(wxTreeItemId()); \ event.Skip(); \ }*/ /*TREE_EVENT_HANDLER(OnBeginRDrag)*/ /*TREE_EVENT_HANDLER(OnDeleteItem)*/ /*TREE_EVENT_HANDLER(OnGetInfo) TREE_EVENT_HANDLER(OnSetInfo)*/ /*TREE_EVENT_HANDLER(OnItemExpanded) TREE_EVENT_HANDLER(OnItemExpanding)*/ /*TREE_EVENT_HANDLER(OnItemCollapsed)*/ /*TREE_EVENT_HANDLER(OnSelChanged) TREE_EVENT_HANDLER(OnSelChanging)*/ /*#undef TREE_EVENT_HANDLER*/ void OPJMarkerTree::OnItemExpanding(wxTreeEvent& event) { wxTreeItemId item = event.GetItem(); OPJMarkerData* data = (OPJMarkerData *) GetItemData(item); wxString text; if (item.IsOk()) text << wxT('"') << GetItemText(item).c_str() << wxT('"'); else text = wxT("invalid item"); if (wxStrcmp(data->GetDesc1(), wxT("INFO-CSTREAM"))) return; wxLogMessage(wxT("Expanding... (%s -> %s, %s, %d, %d)"), text.c_str(), data->GetDesc1(), data->GetDesc2(), data->m_start, data->m_length); // the codestream box is being asked for expansion wxTreeItemIdValue cookie; if (!GetFirstChild(item, cookie).IsOk()) { OPJParseThread *pthread = CreateParseThread(item); if (pthread->Run() != wxTHREAD_NO_ERROR) wxLogMessage(wxT("Can't start parse thread!")); else wxLogMessage(wxT("New parse thread started.")); } } void OPJMarkerTree::OnSelChanged(wxTreeEvent& event) { int bunch_linesize = 16; int bunch_numlines = 7; wxTreeItemId item = event.GetItem(); OPJMarkerData* data = (OPJMarkerData *) GetItemData(item); wxString text; int l, c, pos = 0, pre_pos; m_peektextCtrl->Clear(); /*text << wxString::Format(wxT("Selected... (%s -> %s, %s, %d, %d)"), text.c_str(), data->GetDesc1(), data->GetDesc2(), data->m_start, data->m_length) << wxT("\n");*/ // open the file and browse a little wxFile *fp = new wxFile(m_fname.GetFullPath().c_str(), wxFile::read); // go to position claimed fp->Seek(data->m_start, wxFromStart); // read a bunch int max_read = wxMin(wxFileOffset(bunch_linesize * bunch_numlines), data->m_length - data->m_start + 1); if (data->m_desc == wxT("MARK (65380)")) { /*wxLogMessage(data->m_desc);*/ max_read = data->m_length - data->m_start + 1; bunch_numlines = (int) ceil((float) max_read / (float) bunch_linesize); } unsigned char *buffer = new unsigned char[bunch_linesize * bunch_numlines]; fp->Read(buffer, max_read); // write the file data between start and stop pos = 0; for (l = 0; l < bunch_numlines; l++) { text << wxString::Format(wxT("%010d:"), data->m_start + pos); pre_pos = pos; // add hex browsing text for (c = 0; c < bunch_linesize; c++) { if (!(c % 8)) text << wxT(" "); if (pos < max_read) { text << wxString::Format(wxT("%02X "), buffer[pos]); } else text << wxT(" "); pos++; } text << wxT(" "); // add char browsing text for (c = 0; c < bunch_linesize; c++) { if (pre_pos < max_read) { if ((buffer[pre_pos] == '\n') || (buffer[pre_pos] == '\t') || (buffer[pre_pos] == '\0') || (buffer[pre_pos] == 0x0D) || (buffer[pre_pos] == 0x0B)) buffer[pre_pos] = ' '; text << wxString::FromAscii((char) buffer[pre_pos]) << wxT("."); } else text << wxT(" "); pre_pos++; } text << wxT("\n"); } // close the file fp->Close(); m_peektextCtrl->WriteText(text); delete buffer; } /*void LogKeyEvent(const wxChar *name, const wxKeyEvent& event) { wxString key; long keycode = event.GetKeyCode(); { switch ( keycode ) { case WXK_BACK: key = wxT("BACK"); break; case WXK_TAB: key = wxT("TAB"); break; case WXK_RETURN: key = wxT("RETURN"); break; case WXK_ESCAPE: key = wxT("ESCAPE"); break; case WXK_SPACE: key = wxT("SPACE"); break; case WXK_DELETE: key = wxT("DELETE"); break; case WXK_START: key = wxT("START"); break; case WXK_LBUTTON: key = wxT("LBUTTON"); break; case WXK_RBUTTON: key = wxT("RBUTTON"); break; case WXK_CANCEL: key = wxT("CANCEL"); break; case WXK_MBUTTON: key = wxT("MBUTTON"); break; case WXK_CLEAR: key = wxT("CLEAR"); break; case WXK_SHIFT: key = wxT("SHIFT"); break; case WXK_ALT: key = wxT("ALT"); break; case WXK_CONTROL: key = wxT("CONTROL"); break; case WXK_MENU: key = wxT("MENU"); break; case WXK_PAUSE: key = wxT("PAUSE"); break; case WXK_CAPITAL: key = wxT("CAPITAL"); break; case WXK_END: key = wxT("END"); break; case WXK_HOME: key = wxT("HOME"); break; case WXK_LEFT: key = wxT("LEFT"); break; case WXK_UP: key = wxT("UP"); break; case WXK_RIGHT: key = wxT("RIGHT"); break; case WXK_DOWN: key = wxT("DOWN"); break; case WXK_SELECT: key = wxT("SELECT"); break; case WXK_PRINT: key = wxT("PRINT"); break; case WXK_EXECUTE: key = wxT("EXECUTE"); break; case WXK_SNAPSHOT: key = wxT("SNAPSHOT"); break; case WXK_INSERT: key = wxT("INSERT"); break; case WXK_HELP: key = wxT("HELP"); break; case WXK_NUMPAD0: key = wxT("NUMPAD0"); break; case WXK_NUMPAD1: key = wxT("NUMPAD1"); break; case WXK_NUMPAD2: key = wxT("NUMPAD2"); break; case WXK_NUMPAD3: key = wxT("NUMPAD3"); break; case WXK_NUMPAD4: key = wxT("NUMPAD4"); break; case WXK_NUMPAD5: key = wxT("NUMPAD5"); break; case WXK_NUMPAD6: key = wxT("NUMPAD6"); break; case WXK_NUMPAD7: key = wxT("NUMPAD7"); break; case WXK_NUMPAD8: key = wxT("NUMPAD8"); break; case WXK_NUMPAD9: key = wxT("NUMPAD9"); break; case WXK_MULTIPLY: key = wxT("MULTIPLY"); break; case WXK_ADD: key = wxT("ADD"); break; case WXK_SEPARATOR: key = wxT("SEPARATOR"); break; case WXK_SUBTRACT: key = wxT("SUBTRACT"); break; case WXK_DECIMAL: key = wxT("DECIMAL"); break; case WXK_DIVIDE: key = wxT("DIVIDE"); break; case WXK_F1: key = wxT("F1"); break; case WXK_F2: key = wxT("F2"); break; case WXK_F3: key = wxT("F3"); break; case WXK_F4: key = wxT("F4"); break; case WXK_F5: key = wxT("F5"); break; case WXK_F6: key = wxT("F6"); break; case WXK_F7: key = wxT("F7"); break; case WXK_F8: key = wxT("F8"); break; case WXK_F9: key = wxT("F9"); break; case WXK_F10: key = wxT("F10"); break; case WXK_F11: key = wxT("F11"); break; case WXK_F12: key = wxT("F12"); break; case WXK_F13: key = wxT("F13"); break; case WXK_F14: key = wxT("F14"); break; case WXK_F15: key = wxT("F15"); break; case WXK_F16: key = wxT("F16"); break; case WXK_F17: key = wxT("F17"); break; case WXK_F18: key = wxT("F18"); break; case WXK_F19: key = wxT("F19"); break; case WXK_F20: key = wxT("F20"); break; case WXK_F21: key = wxT("F21"); break; case WXK_F22: key = wxT("F22"); break; case WXK_F23: key = wxT("F23"); break; case WXK_F24: key = wxT("F24"); break; case WXK_NUMLOCK: key = wxT("NUMLOCK"); break; case WXK_SCROLL: key = wxT("SCROLL"); break; case WXK_PAGEUP: key = wxT("PAGEUP"); break; case WXK_PAGEDOWN: key = wxT("PAGEDOWN"); break; case WXK_NUMPAD_SPACE: key = wxT("NUMPAD_SPACE"); break; case WXK_NUMPAD_TAB: key = wxT("NUMPAD_TAB"); break; case WXK_NUMPAD_ENTER: key = wxT("NUMPAD_ENTER"); break; case WXK_NUMPAD_F1: key = wxT("NUMPAD_F1"); break; case WXK_NUMPAD_F2: key = wxT("NUMPAD_F2"); break; case WXK_NUMPAD_F3: key = wxT("NUMPAD_F3"); break; case WXK_NUMPAD_F4: key = wxT("NUMPAD_F4"); break; case WXK_NUMPAD_HOME: key = wxT("NUMPAD_HOME"); break; case WXK_NUMPAD_LEFT: key = wxT("NUMPAD_LEFT"); break; case WXK_NUMPAD_UP: key = wxT("NUMPAD_UP"); break; case WXK_NUMPAD_RIGHT: key = wxT("NUMPAD_RIGHT"); break; case WXK_NUMPAD_DOWN: key = wxT("NUMPAD_DOWN"); break; case WXK_NUMPAD_PAGEUP: key = wxT("NUMPAD_PAGEUP"); break; case WXK_NUMPAD_PAGEDOWN: key = wxT("NUMPAD_PAGEDOWN"); break; case WXK_NUMPAD_END: key = wxT("NUMPAD_END"); break; case WXK_NUMPAD_BEGIN: key = wxT("NUMPAD_BEGIN"); break; case WXK_NUMPAD_INSERT: key = wxT("NUMPAD_INSERT"); break; case WXK_NUMPAD_DELETE: key = wxT("NUMPAD_DELETE"); break; case WXK_NUMPAD_EQUAL: key = wxT("NUMPAD_EQUAL"); break; case WXK_NUMPAD_MULTIPLY: key = wxT("NUMPAD_MULTIPLY"); break; case WXK_NUMPAD_ADD: key = wxT("NUMPAD_ADD"); break; case WXK_NUMPAD_SEPARATOR: key = wxT("NUMPAD_SEPARATOR"); break; case WXK_NUMPAD_SUBTRACT: key = wxT("NUMPAD_SUBTRACT"); break; case WXK_NUMPAD_DECIMAL: key = wxT("NUMPAD_DECIMAL"); break; default: { if ( keycode < 128 && wxIsprint((int)keycode) ) key.Printf(wxT("'%c'"), (char)keycode); else if ( keycode > 0 && keycode < 27 ) key.Printf(_("Ctrl-%c"), wxT('A') + keycode - 1); else key.Printf(wxT("unknown (%ld)"), keycode); } } } wxLogMessage(wxT("%s event: %s (flags = %c%c%c%c)"), name, key.c_str(), event.ControlDown() ? wxT('C') : wxT('-'), event.AltDown() ? wxT('A') : wxT('-'), event.ShiftDown() ? wxT('S') : wxT('-'), event.MetaDown() ? wxT('M') : wxT('-')); } void OPJMarkerTree::OnTreeKeyDown(wxTreeEvent& event) { LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent()); event.Skip(); }*/ /*void OPJMarkerTree::OnBeginDrag(wxTreeEvent& event) { // need to explicitly allow drag if ( event.GetItem() != GetRootItem() ) { m_draggedItem = event.GetItem(); wxLogMessage(wxT("OnBeginDrag: started dragging %s"), GetItemText(m_draggedItem).c_str()); event.Allow(); } else { wxLogMessage(wxT("OnBeginDrag: this item can't be dragged.")); } } void OPJMarkerTree::OnEndDrag(wxTreeEvent& event) { wxTreeItemId itemSrc = m_draggedItem, itemDst = event.GetItem(); m_draggedItem = (wxTreeItemId)0l; // where to copy the item? if ( itemDst.IsOk() && !ItemHasChildren(itemDst) ) { // copy to the parent then itemDst = GetItemParent(itemDst); } if ( !itemDst.IsOk() ) { wxLogMessage(wxT("OnEndDrag: can't drop here.")); return; } wxString text = GetItemText(itemSrc); wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."), text.c_str(), GetItemText(itemDst).c_str()); // just do append here - we could also insert it just before/after the item // on which it was dropped, but this requires slightly more work... we also // completely ignore the client data and icon of the old item but could // copy them as well. // // Finally, we only copy one item here but we might copy the entire tree if // we were dragging a folder. int image = wxGetApp().ShowImages() ? TreeCtrlIcon_File : -1; AppendItem(itemDst, text, image); }*/ /*void OPJMarkerTree::OnBeginLabelEdit(wxTreeEvent& event) { wxLogMessage(wxT("OnBeginLabelEdit")); // for testing, prevent this item's label editing wxTreeItemId itemId = event.GetItem(); if ( IsTestItem(itemId) ) { wxMessageBox(wxT("You can't edit this item.")); event.Veto(); } else if ( itemId == GetRootItem() ) { // test that it is possible to change the text of the item being edited SetItemText(itemId, _T("Editing root item")); } } void OPJMarkerTree::OnEndLabelEdit(wxTreeEvent& event) { wxLogMessage(wxT("OnEndLabelEdit")); // don't allow anything except letters in the labels if ( !event.GetLabel().IsWord() ) { wxMessageBox(wxT("The new label should be a single word.")); event.Veto(); } }*/ /*void OPJMarkerTree::OnItemCollapsing(wxTreeEvent& event) { wxLogMessage(wxT("OnItemCollapsing")); // for testing, prevent the user from collapsing the first child folder wxTreeItemId itemId = event.GetItem(); if ( IsTestItem(itemId) ) { wxMessageBox(wxT("You can't collapse this item.")); event.Veto(); } }*/ /*void OPJMarkerTree::OnItemActivated(wxTreeEvent& event) { // show some info about this item wxTreeItemId itemId = event.GetItem(); OPJMarkerData *item = (OPJMarkerData *)GetItemData(itemId); if ( item != NULL ) { item->ShowInfo(this); } wxLogMessage(wxT("OnItemActivated")); }*/ void OPJMarkerTree::OnItemMenu(wxTreeEvent& event) { /*wxTreeItemId itemId = event.GetItem(); OPJMarkerData *item = itemId.IsOk() ? (OPJMarkerData *)GetItemData(itemId) : NULL; wxLogMessage(wxT("OnItemMenu for item \"%s\""), item ? item->GetDesc() : _T(""));*/ //wxLogMessage(wxT("EEEEEEEEEE")); //event.Skip(); } /*void OPJMarkerTree::OnContextMenu(wxContextMenuEvent& event) { wxPoint pt = event.GetPosition(); wxTreeItemId item; wxLogMessage(wxT("OnContextMenu at screen coords (%i, %i)"), pt.x, pt.y); // check if event was generated by keyboard (MSW-specific?) if ( pt.x == -1 && pt.y == -1 ) //(this is how MSW indicates it) { if ( !HasFlag(wxTR_MULTIPLE) ) item = GetSelection(); // attempt to guess where to show the menu if ( item.IsOk() ) { // if an item was clicked, show menu to the right of it wxRect rect; GetBoundingRect(item, rect, true );// only the label pt = wxPoint(rect.GetRight(), rect.GetTop()); } else { pt = wxPoint(0, 0); } } else // event was generated by mouse, use supplied coords { pt = ScreenToClient(pt); item = HitTest(pt); } ShowMenu(item, pt); }*/ /*void OPJMarkerTree::ShowMenu(wxTreeItemId id, const wxPoint& pt) { wxString title; if ( id.IsOk() ) { title << wxT("Menu for ") << GetItemText(id); } else { title = wxT("Menu for no particular item"); } #if wxUSE_MENUS wxMenu menu(title); menu.Append(TreeTest_About, wxT("&About...")); menu.AppendSeparator(); menu.Append(TreeTest_Highlight, wxT("&Highlight item")); menu.Append(TreeTest_Dump, wxT("&Dump")); PopupMenu(&menu, pt); #endif // wxUSE_MENUS }*/ /*void OPJMarkerTree::OnItemRClick(wxTreeEvent& event) { wxTreeItemId itemId = event.GetItem(); OPJMarkerData *item = itemId.IsOk() ? (OPJMarkerData *)GetItemData(itemId) : NULL; wxLogMessage(wxT("Item \"%s\" right clicked"), item ? item->GetDesc() : _T("")); event.Skip(); }*/ /* void OPJMarkerTree::OnRMouseDown(wxMouseEvent& event) { wxLogMessage(wxT("Right mouse button down")); event.Skip(); } void OPJMarkerTree::OnRMouseUp(wxMouseEvent& event) { wxLogMessage(wxT("Right mouse button up")); event.Skip(); } void OPJMarkerTree::OnRMouseDClick(wxMouseEvent& event) { wxTreeItemId id = HitTest(event.GetPosition()); if ( !id ) wxLogMessage(wxT("No item under mouse")); else { OPJMarkerData *item = (OPJMarkerData *)GetItemData(id); if ( item ) wxLogMessage(wxT("Item '%s' under mouse"), item->GetDesc()); } event.Skip(); } */ static inline const wxChar *Bool2String(bool b) { return b ? wxT("") : wxT("not "); } void OPJMarkerData::ShowInfo(wxTreeCtrl *tree) { wxLogMessage(wxT("Item '%s': %sselected, %sexpanded, %sbold,\n") wxT("%u children (%u immediately under this item)."), m_desc.c_str(), Bool2String(tree->IsSelected(GetId())), Bool2String(tree->IsExpanded(GetId())), Bool2String(tree->IsBold(GetId())), unsigned(tree->GetChildrenCount(GetId())), unsigned(tree->GetChildrenCount(GetId(), false))); }