From f49a506e7b6b420cbe67a65e1538f5a0162ff850 Mon Sep 17 00:00:00 2001 From: maxieds Date: Thu, 12 Jul 2018 05:51:34 -0400 Subject: [PATCH] Currently the Cairo buffer is not getting drawn correctly --- src/BranchTypeIdentification.cpp | 263 ++++++ src/BranchTypeIdentification.h | 103 +++ src/DiagramWindow.cpp | 1485 ++++++++++++++++-------------- src/DiagramWindow.h | 46 +- src/RNAStructViz.cpp | 2 +- src/RNAStructure.cpp | 108 ++- src/RNAStructure.h | 85 +- src/StatsWindow.h | 2 + 8 files changed, 1345 insertions(+), 749 deletions(-) create mode 100644 src/BranchTypeIdentification.cpp create mode 100644 src/BranchTypeIdentification.h diff --git a/src/BranchTypeIdentification.cpp b/src/BranchTypeIdentification.cpp new file mode 100644 index 0000000..e8f4de3 --- /dev/null +++ b/src/BranchTypeIdentification.cpp @@ -0,0 +1,263 @@ +/* BranchTypeIdentification.cpp + Author: Maxie D. Schmidt (maxieds@gmail.com) + Created: 2018.06.16 +*/ + +#include +#include +#include + +#include +#include +using std::vector; +using std::sort; + +#include "BranchTypeIdentification.h" +//#include "Utils.h" + +vector RNABranchType_t::getEnclosingArcs( + RNAStructure * &rnaStructBase, bool removeTopFour = false) { + vector rBaseDataVec; + for(int bd = 0; bd < rnaStructBase->GetLength(); bd++) { + bool isAlreadyEnclosed = false; + RNAStructure::BaseData *curBaseData = rnaStructBase->GetBaseAt(bd); + for(int v = 0; v < rBaseDataVec.size(); v++) { + if(curBaseData->m_pair == RNAStructure::UNPAIRED) { + isAlreadyEnclosed = true; + break; + } + else if(curBaseData->isContainedIn(*(rBaseDataVec[v]))) { + isAlreadyEnclosed = true; + break; + } + else if(rBaseDataVec[v]->isContainedIn(*curBaseData)) { + rBaseDataVec[v] = curBaseData; + isAlreadyEnclosed = true; + break; + } + } + if(!isAlreadyEnclosed && (rBaseDataVec.size() > 0 || curBaseData->m_pair != RNAStructure::UNPAIRED)) { + rBaseDataVec.push_back(curBaseData); + } + } + sort(rBaseDataVec.begin(), rBaseDataVec.end(), RNAStructureBaseDataArcLengthSort()); + if(removeTopFour) { + rBaseDataVec.erase(rBaseDataVec.begin(), rBaseDataVec.begin() + 4); + } + return rBaseDataVec; +} + +RNABranchType_t::RNABranchType_t(BranchID_t bid = BRANCH_UNDEFINED, class RNAStructure::BaseData *bparent = NULL) { + branchID = bid; + branchParent = bparent; +} + +RNABranchType_t & RNABranchType_t::operator=(const BranchID_t &rhs) { + setBranchID(rhs); + branchParent = NULL; + return *this; +} + +bool RNABranchType_t::operator==(const RNABranchType_t &rhs) const { + return branchID == rhs.branchID && branchParent == rhs.branchParent; +} + +bool RNABranchType_t::operator==(const BranchID_t &rhs) const { + return branchID == rhs; +} + +const BranchID_t & RNABranchType_t::getBranchID() const { + return branchID; +} + +void RNABranchType_t::setBranchID(BranchID_t bid) { + branchID = bid; +} + +const RNAStructure::BaseData* RNABranchType_t::getBranchParent() const { + return branchParent; +} + +void RNABranchType_t::setBranchParent(class RNAStructure::BaseData* bparent) { + branchParent = bparent; +} + +void RNABranchType_t::SetBranchColor(cairo_t * &cr, BranchID_t bt) { + switch(bt) { + case BRANCH_UNDEFINED: + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + break; + case BRANCH1: + cairo_set_source_rgb(cr, 92.0 / 255, 160.0 / 255, 215.0 / 255); + break; + case BRANCH2: + cairo_set_source_rgb(cr, 183.0 / 255, 127.0 / 255, 77.0 / 255); + break; + case BRANCH3: + cairo_set_source_rgb(cr, 243.0 / 255, 153.0 / 255, 193.0 / 255); + break; + case BRANCH4: + cairo_set_source_rgb(cr, 123.0 / 255, 204.0 / 255, 153.0 / 255); + break; + default: + break; + } +} + +bool RNABranchType_t::PerformBranchClassification(class RNAStructure * &rnaStructBase, unsigned int alength) { + + if(alength < 4) + return false; + + // first we determine the four most enclosing arcs on the circle: + RNAStructure::BaseData* mostEnclosingArcs[4] = {NULL, NULL, NULL, NULL}; + unsigned int mostEnclosingArcsSize = 0; + for(int rs = 0; rs < alength; rs++) { + //fprintf(stderr, "[1] rs=%d\n", rs); + RNAStructure::BaseData* rnaStruct = rnaStructBase->GetBaseAt(rs); + if(rnaStruct->m_pair == RNAStructure::UNPAIRED) + continue; + else if(mostEnclosingArcsSize == 0) { + mostEnclosingArcs[0] = rnaStructBase->GetBaseAt(rs); + //fprintf(stderr, "mostEnclosingArcs[0]=%p\n", mostEnclosingArcs[0]); + mostEnclosingArcsSize++; + continue; + } + bool isEnclosedInLargerBranch = false; + for(int mea = 0; mea < mostEnclosingArcsSize; mea++) { + if(rnaStruct->isContainedIn(*(mostEnclosingArcs[mea]))) { + isEnclosedInLargerBranch = true; + //rnaStructBase->GetBranchTypeAt(rs).setBranchID((BranchID_t) (mea + 1)); + //rnaStructBase->GetBranchTypeAt(rs).setBranchParent(mostEnclosingArcs[mea]); + break; + } + } + if(isEnclosedInLargerBranch) + continue; // this cannot be an outer containing branch + RNAStructure::BaseData *currentBaseData = rnaStructBase->GetBaseAt(rs);; + unsigned int pairDistance = ABS(MAX(currentBaseData->m_pair, currentBaseData->m_index) - + MIN(currentBaseData->m_pair, currentBaseData->m_index)); + for(int mea = 0; mea < mostEnclosingArcsSize; mea++) { + RNAStructure::BaseData *meaBaseData = mostEnclosingArcs[mea]; + unsigned int meaPairDistance = ABS(MAX(meaBaseData->m_pair, meaBaseData->m_index) - + MIN(meaBaseData->m_pair, meaBaseData->m_index)); + bool needToResort = false; + if(meaPairDistance < pairDistance && meaBaseData->m_pair > meaBaseData->m_index) { + //fprintf(stderr, "[2] meaPD=%d, PD=%d\n", meaPairDistance, pairDistance); + if(mostEnclosingArcsSize < 4) { + mostEnclosingArcs[mostEnclosingArcsSize] = mostEnclosingArcs[mea]; + mostEnclosingArcsSize++; + needToResort = true; + } + mostEnclosingArcs[mea] = rnaStructBase->GetBaseAt(rs); + //rnaStructBase->GetBranchTypeAt(rs)->setBranchID((BranchID_t) (mea + 1)); + if(needToResort) { + qsort(&mostEnclosingArcs[0], mostEnclosingArcsSize, + sizeof(RNAStructure::BaseData*), compareMostEnclosingArcs); + } + break; + } + } + } + // sort the identified branches according to their natural order on the circle: + IntIndexPair_t branchOrderMappings[mostEnclosingArcsSize]; + for(int i = 0; i < mostEnclosingArcsSize; i++) { + branchOrderMappings[i].intValue = MIN(mostEnclosingArcs[i]->m_index, mostEnclosingArcs[i]->m_pair); + branchOrderMappings[i].index = i; + } + qsort(&branchOrderMappings[0], mostEnclosingArcsSize, sizeof(IntIndexPair_t), compareIntegerIndexPair); + RNAStructure::BaseData* mostEnclosingArcsTemp[4]; + for(int j = 0; j < mostEnclosingArcsSize; j++) { + mostEnclosingArcsTemp[j] = mostEnclosingArcs[branchOrderMappings[j].index]; + } + for(int k = 0; k < mostEnclosingArcsSize; k++) { + mostEnclosingArcs[k] = mostEnclosingArcsTemp[k]; + } + // now that we've identified most of the the enclosing branches, + // we reset the branch types by number on all (except for the nubbins, + // see below) entries in the array: + vector enclosingArcs = getEnclosingArcs(rnaStructBase, false); + sort(enclosingArcs.begin(), enclosingArcs.begin() + 4, RNAStructureBaseDataIndexSort()); + if(enclosingArcs.size() < 7 || mostEnclosingArcsSize < 4) { + fprintf(stderr, "HUGE LOGISTICAL ERROR: There are not 7 / 4 main arcs / branches to classify!\n"); + return false; + } + // handle labeling of the arc nubbins (and contained pairs) to the sides of the big arcs: + vector enclosingArcsNubbins(enclosingArcs.begin() + 4, enclosingArcs.begin() + 7); + sort(enclosingArcsNubbins.begin(), enclosingArcsNubbins.end(), RNAStructureBaseDataIndexSort()); + BranchID_t nubbinBranchIDs[3] = {BRANCH1, BRANCH2, BRANCH4}; + for(int n = 0; n < 3; n++) { + rnaStructBase->GetBranchTypeAt(enclosingArcsNubbins[n]->m_index)->setBranchID(nubbinBranchIDs[n]); + rnaStructBase->GetBranchTypeAt(enclosingArcsNubbins[n]->m_index)->setBranchParent(enclosingArcs[(int) (nubbinBranchIDs[n] - 1)]); + rnaStructBase->GetBranchTypeAt(enclosingArcsNubbins[n]->m_pair)->setBranchID(nubbinBranchIDs[n]); + rnaStructBase->GetBranchTypeAt(enclosingArcsNubbins[n]->m_pair)->setBranchParent(enclosingArcs[(int) (nubbinBranchIDs[n] - 1)]); + for(int b = 0; b < alength; b++) { + RNAStructure::BaseData *curBase = rnaStructBase->GetBaseAt(b); + if(curBase->isContainedIn(*(enclosingArcsNubbins[n])) || + curBase->m_pair == RNAStructure::UNPAIRED && + curBase->m_index < MAX(enclosingArcsNubbins[n]->m_index, enclosingArcsNubbins[n]->m_pair) && + curBase->m_index > MIN(enclosingArcsNubbins[n]->m_index, enclosingArcsNubbins[n]->m_pair)) { + rnaStructBase->GetBranchTypeAt(b)->setBranchID(nubbinBranchIDs[n]); + rnaStructBase->GetBranchTypeAt(b)->setBranchParent(enclosingArcs[(int) (nubbinBranchIDs[n] - 1)]); + } + } + } + // handle labeling of the big arcs (and contained pairs and unpaired components contained within): + for(int k = 0; k < 4; k++) { + rnaStructBase->GetBranchTypeAt(enclosingArcs[k]->m_index)->setBranchID((BranchID_t) (k + 1)); + rnaStructBase->GetBranchTypeAt(enclosingArcs[k]->m_index)->setBranchParent(enclosingArcs[k]); + rnaStructBase->GetBranchTypeAt(enclosingArcs[k]->m_pair)->setBranchID((BranchID_t) (k + 1)); + rnaStructBase->GetBranchTypeAt(enclosingArcs[k]->m_pair)->setBranchParent(enclosingArcs[k]); + for(int b = 0; b < alength; b++) { + RNAStructure::BaseData *curBase = rnaStructBase->GetBaseAt(b); + if(curBase->isContainedIn(*(enclosingArcs[k])) || + (curBase->m_pair == RNAStructure::UNPAIRED && curBase->m_index < MAX(enclosingArcs[k]->m_index, enclosingArcs[k]->m_pair) && + curBase->m_index > MIN(enclosingArcs[k]->m_index, enclosingArcs[k]->m_pair))) { + rnaStructBase->GetBranchTypeAt(b)->setBranchID((BranchID_t) (k + 1)); + rnaStructBase->GetBranchTypeAt(b)->setBranchParent(enclosingArcs[k]); + } + } + } + // handle labeling of the unpaired components in between the big arcs: + for(int b = 0; b < 4; b++) { + int unpairedBetweenBranchCount = 0; + vector unpairedBetweenVec; + for(int v = 0; v < alength; v++) { + RNAStructure::BaseData *curUnpaired = rnaStructBase->GetBaseAt(v); + if(curUnpaired->isContainedIn(*(enclosingArcs[b])) || + curUnpaired->m_index == enclosingArcs[b]->m_pair && curUnpaired->m_pair == enclosingArcs[b]->m_index) { + rnaStructBase->GetBranchTypeAt(v)->setBranchID((BranchID_t) (b + 1)); + rnaStructBase->GetBranchTypeAt(v)->setBranchParent(enclosingArcs[b]); + } + else if(curUnpaired->m_pair == RNAStructure::UNPAIRED && + curUnpaired->m_index > MAX(enclosingArcs[b]->m_pair, enclosingArcs[b]->m_index) && (b == 3 || + curUnpaired->m_index < MIN(enclosingArcs[b + 1]->m_pair, enclosingArcs[b + 1]->m_index))) { // we want the unpaired bases between branches <- : + unpairedBetweenBranchCount++; + unpairedBetweenVec.push_back(curUnpaired); + } + } + for(int up = 0; up < unpairedBetweenVec.size(); up++) { + if(b < 3 && up <= unpairedBetweenVec.size() / 2) { + rnaStructBase->GetBranchTypeAt(unpairedBetweenVec[up]->m_index)->setBranchID((BranchID_t) (b + 1)); + rnaStructBase->GetBranchTypeAt(unpairedBetweenVec[up]->m_index)->setBranchParent(enclosingArcs[b]); + } + else if(b < 3) { + rnaStructBase->GetBranchTypeAt(unpairedBetweenVec[up]->m_index)->setBranchID((BranchID_t) (b + 2)); + rnaStructBase->GetBranchTypeAt(unpairedBetweenVec[up]->m_index)->setBranchParent(enclosingArcs[b + 1]); + } + else { + rnaStructBase->GetBranchTypeAt(unpairedBetweenVec[up]->m_index)->setBranchID(BRANCH4); + rnaStructBase->GetBranchTypeAt(unpairedBetweenVec[up]->m_index)->setBranchParent(enclosingArcs[3]); + } + } + } + // handle labeling of the unpaired components before the first big arc: + for(int up = 0; up < alength; up++) { + RNAStructure::BaseData *curUnpaired = rnaStructBase->GetBaseAt(up); + if(curUnpaired->m_index < MIN(enclosingArcs[0]->m_index, enclosingArcs[0]->m_pair) && curUnpaired->m_pair == RNAStructure::UNPAIRED) { + rnaStructBase->GetBranchTypeAt(up)->setBranchID(BRANCH1); + rnaStructBase->GetBranchTypeAt(up)->setBranchParent(enclosingArcs[0]); + } + } + return true; +} diff --git a/src/BranchTypeIdentification.h b/src/BranchTypeIdentification.h new file mode 100644 index 0000000..6e1730c --- /dev/null +++ b/src/BranchTypeIdentification.h @@ -0,0 +1,103 @@ +/* BranchTypeIdentification.h : + A helper class to identify which of the four branch types + to which the RNAStructure and/or pairing belongs. + Author: Maxie D. Schmidt (maxieds@gmail.com) + Created: 2018.06.16 +*/ + +#ifndef __RNABRANCHTYPEIDENT_H__ +#define __RNABRANCHTYPEIDENT_H__ + +#include +#include +#include +using std::vector; +using std::sort; + +#include "RNAStructure.h" + +#define NUM_BRANCHES (4) + +typedef enum { + BRANCH1 = 1, + BRANCH2 = 2, + BRANCH3 = 3, + BRANCH4 = 4, + BRANCH_UNDEFINED = 0 +} BranchID_t; + +typedef struct { + int index; + int intValue; +} IntIndexPair_t; + +inline int compareIntegerIndexPair(const void *ip1, const void *ip2) { + int i1 = ((IntIndexPair_t*) ip1)->intValue, i2 = ((IntIndexPair_t*) ip2)->intValue; + if(i1 < i2) + return -1; + else if(i1 == i2) + return 0; + else + return 1; +} + +inline int compareMostEnclosingArcs(const void *arc1, const void *arc2) { + RNAStructure::BaseData *rnaStruct1 = (RNAStructure::BaseData *) arc1; + RNAStructure::BaseData *rnaStruct2 = (RNAStructure::BaseData *) arc2; + unsigned int arc1PairDist = rnaStruct1->getPairDistance(); + unsigned int arc2PairDist = rnaStruct2->getPairDistance(); + if(arc1PairDist < arc2PairDist) + return -1; + else if(arc1PairDist == arc2PairDist) + return 0; + else + return 1; +} + +class RNABranchType_t { + + protected: + static vector getEnclosingArcs( + RNAStructure * &rnaStructBase, bool removeTopFour); + + public: + RNABranchType_t(BranchID_t bid, class RNAStructure::BaseData *bparent); + + RNABranchType_t & operator=(const BranchID_t &rhs); + + bool operator==(const RNABranchType_t &rhs) const; + bool operator==(const BranchID_t &rhs) const; + + const BranchID_t & getBranchID() const; + void setBranchID(BranchID_t bid); + + const RNAStructure::BaseData* getBranchParent() const; + void setBranchParent(class RNAStructure::BaseData* bparent); + + static void SetBranchColor(cairo_t * &cr, BranchID_t bt); + + static bool PerformBranchClassification(class RNAStructure * &rnaStructArray, unsigned int alength); + + protected: + BranchID_t branchID; + RNAStructure::BaseData *branchParent; + + + public: + typedef struct { + inline bool operator()(RNAStructure::BaseData *bd1, RNAStructure::BaseData *bd2) { // sorts in decreasing order (i.e., largest arcs first): + int bd1ArcDist = (bd1->m_pair == RNAStructure::UNPAIRED) ? 0 : MAX(bd1->m_index, bd1->m_pair) - MIN(bd1->m_index, bd1->m_pair); + int bd2ArcDist = (bd2->m_pair == RNAStructure::UNPAIRED) ? 0 : MAX(bd2->m_index, bd2->m_pair) - MIN(bd2->m_index, bd2->m_pair); + return bd1ArcDist > bd2ArcDist; + } + } RNAStructureBaseDataArcLengthSort; + + typedef struct { + inline bool operator()(RNAStructure::BaseData *bd1, RNAStructure::BaseData *bd2) { + return bd1->m_index < bd2->m_index; + } + } RNAStructureBaseDataIndexSort; + +}; + +#endif diff --git a/src/DiagramWindow.cpp b/src/DiagramWindow.cpp index 520c4a8..e4aa2c0 100755 --- a/src/DiagramWindow.cpp +++ b/src/DiagramWindow.cpp @@ -1,19 +1,22 @@ #include "DiagramWindow.h" #include "RNAStructViz.h" +#include "BranchTypeIdentification.h" #include #include +#include +#include #include #include #include #include #include +#include const int DiagramWindow::ms_menu_minx[3] = {5, 205, 405}; -const int DiagramWindow::ms_menu_width = 190; +const int DiagramWindow::ms_menu_width = 190; + +void DiagramWindow::Construct(int w, int h, const std::vector &structures) { -void DiagramWindow::Construct(int w, int h, const std::vector& structures) -{ - m_offscreenImage[0] = fl_create_offscreen(2048, 2048); m_imageData[0] = new uchar[2048 * 2048 * 3]; memset(m_imageData[0], 0, 2048 * 2048 * 3); @@ -21,129 +24,160 @@ void DiagramWindow::Construct(int w, int h, const std::vector& structures) m_imageData[1] = new uchar[1024 * 1024 * 3]; memset(m_imageData[1], 0, 1024 * 1024 * 3); + crSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, IMAGE_WIDTH, IMAGE_WIDTH); + crDraw = cairo_create(crSurface); + CairoPrepareDisplay(); + int s; - if (w > h-120) s = h-120; + if (w > h - 120) s = h - 120; else s = w; - + pixelWidth = 2; - - m_glWindow = new GLWindow(0, 120, s,s); - m_glWindow->SetTextureData(m_imageData[0], 2048); - m_glWindow->SetTextureData(m_imageData[1], 1024); - m_menus[0] = m_menus[1] = m_menus[2] = 0; + //m_glWindow = new GLWindow(0, 120, s,s); + //m_glWindow->SetTextureData(m_imageData[0], 2048); + //m_glWindow->SetTextureData(m_imageData[1], 1024); + CairoDrawBufferToScreen(); + + m_menus[0] = m_menus[1] = m_menus[2] = NULL; m_menuItems = 0; m_menuItemsSize = 0; folderIndex = -1; - + m_drawBranchesIndicator = NULL; + userConflictAlerted = false; + + Fl::visual(FL_RGB); + //colors the top of the Diagram window where structures are chosen - color(FL_WHITE); + color(FL_WHITE); //color(FL_BACKGROUND_COLOR); size_range(580, 700); box(FL_NO_BOX); - Fl_Box* resizeBox = new Fl_Box(0, 120, w, h - 120); + Fl_Box *resizeBox = new Fl_Box(0, 120, w, h - 120); resizable(resizeBox); - - title = (char*)malloc(sizeof(char) * 64); + + title = (char *) malloc(sizeof(char) * 64); SetStructures(structures); } -DiagramWindow::DiagramWindow(int w, int h, const char *label, - const std::vector& structures) - : Fl_Window(w, h, label) - , m_redrawStructures(true) -{ - Construct(w, h, structures); +DiagramWindow::DiagramWindow(int w, int h, const char *label, + const std::vector &structures) + : Fl_Window(w + 150, h, label), m_redrawStructures(true) { + Construct(w + 150, h, structures); } -DiagramWindow::DiagramWindow(int x, int y, int w, int h, const char *label, - const std::vector& structures) - : Fl_Window(x, y, w, h, label) - , m_redrawStructures(true) -{ - Construct(w, h, structures); +DiagramWindow::DiagramWindow(int x, int y, int w, int h, const char *label, + const std::vector &structures) + : Fl_Window(x, y, w + 150, h, label), m_redrawStructures(true) { + Construct(w + 150, h, structures); } -DiagramWindow::~DiagramWindow() -{ +DiagramWindow::~DiagramWindow() { delete[] m_imageData[0]; delete[] m_imageData[1]; - + delete m_drawBranchesIndicator; + cairo_destroy(crDraw); + cairo_surface_destroy(crSurface); + cairo_pattern_destroy(circleMask); free(m_menuItems); } -void DiagramWindow::SetFolderIndex(int index) -{ +void DiagramWindow::SetFolderIndex(int index) { folderIndex = index; - - sprintf(title, "Diagrams: %-.48s", - RNAStructViz::GetInstance()->GetStructureManager()-> - GetFolderAt(index)->folderName); + + sprintf(title, "Diagrams: %-.48s", + RNAStructViz::GetInstance()->GetStructureManager()-> + GetFolderAt(index)->folderName); label(title); } -void DiagramWindow::ResetWindow() -{ - this->size(800,700); - - delete[] m_imageData[0]; - delete[] m_imageData[1]; - m_glWindow->clear(); +void DiagramWindow::ResetWindow(bool resetMenus = true) { + this->size(800 + 150, 700); - m_offscreenImage[0] = fl_create_offscreen(2048, 2048); + delete[] m_imageData[0]; + delete[] m_imageData[1]; + //m_glWindow->clear(); + cairo_destroy(crDraw); + cairo_surface_destroy(crSurface); + cairo_pattern_destroy(circleMask); + + m_offscreenImage[0] = fl_create_offscreen(2048, 2048); m_imageData[0] = new uchar[2048 * 2048 * 3]; memset(m_imageData[0], 0, 2048 * 2048 * 3); m_offscreenImage[1] = fl_create_offscreen(1024, 1024); m_imageData[1] = new uchar[1024 * 1024 * 3]; memset(m_imageData[1], 0, 1024 * 1024 * 3); - m_glWindow->SetTextureData(m_imageData[0], 2048); - m_glWindow->SetTextureData(m_imageData[1], 1024); + crSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, IMAGE_WIDTH, IMAGE_WIDTH); + crDraw = cairo_create(crSurface); + CairoPrepareDisplay(); + + //m_glWindow->SetTextureData(m_imageData[0], 2048); + //m_glWindow->SetTextureData(m_imageData[1], 1024); + CairoDrawBufferToScreen(); + + if (resetMenus) { + m_menus[0]->value(0); + m_menus[1]->value(0); + m_menus[2]->value(0); + m_drawBranchesIndicator->clear(); + userConflictAlerted = false; + } + + redraw(); +} - m_menus[0]->value(0); - m_menus[1]->value(0); - m_menus[2]->value(0); - - redraw(); +void DiagramWindow::checkBoxChangedStateCallback(Fl_Widget *, void *v) { + Fl_Check_Button *cbDrawIndicator = (Fl_Check_Button *) v; + if (cbDrawIndicator->changed()) { + DiagramWindow *thisWindow = (DiagramWindow *) cbDrawIndicator->parent(); + thisWindow->m_redrawStructures = true; + thisWindow->ResetWindow(false); + cbDrawIndicator->clear_changed(); + } } -void DiagramWindow::resize(int x, int y, int w, int h) -{ - Fl_Window::resize(x,y,w,h); +void DiagramWindow::exportToPNGButtonPressHandler(Fl_Widget *, void *v) { + Fl_Button *buttonPressed = (Fl_Button *) v; + if (buttonPressed->changed()) { + DiagramWindow *thisWindow = (DiagramWindow *) buttonPressed->parent(); + char *exportFilePath = thisWindow->GetExportPNGFilePath(); + cairo_surface_write_to_png(thisWindow->crSurface, exportFilePath); + buttonPressed->clear_changed(); + } +} + +void DiagramWindow::resize(int x, int y, int w, int h) { + Fl_Window::resize(x, y, w, h); int s; - if (w > h-120) s = h-120; + if (w > h - 120) s = h - 120; else s = w; - m_glWindow->size(s,s); + //m_glWindow->size(s,s); } -void DiagramWindow::draw() -{ - +void DiagramWindow::draw() { + Fl_Color priorColor = fl_color(); int priorFont = fl_font(); int priorFontSize = fl_size(); - + fl_color(color()); fl_rectf(0, 0, w(), h()); fl_color(priorColor); - + Fl_Window::draw(); // Get the structures. Be sure the reference structure is first. - RNAStructure* sequences[3]; - StructureManager* structureManager = - RNAStructViz::GetInstance()->GetStructureManager(); - for (int j = 0; j < 3; ++j) - { - if ((intptr_t)(m_menuItems[m_menus[j]->value()].user_data()) == -1) - { - sequences[j] = 0; - } - else - { - sequences[j] = structureManager->GetStructure( - (intptr_t)(m_menuItems[m_menus[j]->value()].user_data())); + RNAStructure *sequences[3]; + StructureManager *structureManager = + RNAStructViz::GetInstance()->GetStructureManager(); + for (int j = 0; j < 3; ++j) { + if ((intptr_t) (m_menuItems[m_menus[j]->value()].user_data()) == -1) { + sequences[j] = 0; + } else { + sequences[j] = structureManager->GetStructure( + (intptr_t) (m_menuItems[m_menus[j]->value()].user_data())); if (sequences[j]->GetLength() > 1000) { pixelWidth = 1; } else if (sequences[j]->GetLength() <= 1000 && sequences[j]->GetLength() >= 500) { @@ -151,114 +185,90 @@ void DiagramWindow::draw() } else { pixelWidth = 3; } - } - } + } + } int numToDraw = 0; - if (sequences[0]) - { - if (sequences[1]) - { - if (sequences[2]) - { - numToDraw = 3; - ComputeNumPairs(sequences, 3); - DrawKey3(); - } - else - { - numToDraw = 2; - ComputeNumPairs(sequences, 2); - DrawKey2(0, 1); - } - } - else - { - if (sequences[2]) - { - sequences[1] = sequences[2]; - ComputeNumPairs(sequences, 2); - DrawKey2(0, 2); - numToDraw = 2; - } - else - { - ComputeNumPairs(sequences, 1); - DrawKey1(0); - numToDraw = 1; - } - } - } - else - { - if (sequences[1]) - { - if (sequences[2]) - { - sequences[0] = sequences[1]; - sequences[1] = sequences[2]; - ComputeNumPairs(sequences, 2); - DrawKey2(1, 2); - numToDraw = 2; - } - else - { - sequences[0] = sequences[1]; - ComputeNumPairs(sequences, 1); - DrawKey1(1); - numToDraw = 1; - } - } - else - { - if (sequences[2]) - { - sequences[0] = sequences[2]; - ComputeNumPairs(sequences, 1); - DrawKey1(2); - numToDraw = 1; - } - else - { - numToDraw = 0; - } - } + if (sequences[0]) { + if (sequences[1]) { + if (sequences[2]) { + numToDraw = 3; + ComputeNumPairs(sequences, 3); + DrawKey3(); + } else { + numToDraw = 2; + ComputeNumPairs(sequences, 2); + DrawKey2(0, 1); + } + } else { + if (sequences[2]) { + sequences[1] = sequences[2]; + ComputeNumPairs(sequences, 2); + DrawKey2(0, 2); + numToDraw = 2; + } else { + ComputeNumPairs(sequences, 1); + DrawKey1(0); + numToDraw = 1; + } + } + } else { + if (sequences[1]) { + if (sequences[2]) { + sequences[0] = sequences[1]; + sequences[1] = sequences[2]; + ComputeNumPairs(sequences, 2); + DrawKey2(1, 2); + numToDraw = 2; + } else { + sequences[0] = sequences[1]; + ComputeNumPairs(sequences, 1); + DrawKey1(1); + numToDraw = 1; + } + } else { + if (sequences[2]) { + sequences[0] = sequences[2]; + ComputeNumPairs(sequences, 1); + DrawKey1(2); + numToDraw = 1; + } else { + numToDraw = 0; + } + } } - if (m_redrawStructures) - { - { - fl_begin_offscreen(m_offscreenImage[0]); - RedrawBuffer(sequences, numToDraw, 2048); - fl_read_image(m_imageData[0], 0, 0, 2048, 2048); - fl_end_offscreen(); - } - - { - fl_begin_offscreen(m_offscreenImage[1]); - RedrawBuffer(sequences, numToDraw, 1024); - fl_read_image(m_imageData[1], 0, 0, 1024, 1024); - fl_end_offscreen(); - } - - m_glWindow->UpdateTexture(); - m_redrawStructures = false; + if (m_redrawStructures) { + { + fl_begin_offscreen(m_offscreenImage[0]); + RedrawBuffer(sequences, numToDraw, 2048); + fl_read_image(m_imageData[0], 0, 0, 2048, 2048); + fl_end_offscreen(); + } + + { + fl_begin_offscreen(m_offscreenImage[1]); + RedrawBuffer(sequences, numToDraw, 1024); + fl_read_image(m_imageData[1], 0, 0, 1024, 1024); + fl_end_offscreen(); + } + + //m_glWindow->UpdateTexture(); + m_redrawStructures = false; } - m_glWindow->redraw(); + //m_glWindow->redraw(); fl_color(priorColor); fl_font(priorFont, priorFontSize); fl_line_style(0); - + } -void DiagramWindow::RedrawBuffer(RNAStructure** structures, - const int numStructures, const int resolution) -{ - //fl_color(FL_BACKGROUND_COLOR); - fl_color(FL_WHITE); - fl_rectf(0, 0, resolution, resolution); +void DiagramWindow::RedrawBuffer(RNAStructure **structures, + const int numStructures, const int resolution) { + //fl_color(FL_WHITE); + //fl_rectf(0, 0, resolution, resolution); int priorFont = fl_font(); int priorFontSize = fl_size(); @@ -266,24 +276,18 @@ void DiagramWindow::RedrawBuffer(RNAStructure** structures, fl_line_style(0); - if (numStructures == 1) - { - Draw1(structures, resolution); - } - else if (numStructures == 2) - { - Draw2(structures, resolution); - } - else if (numStructures == 3) - { - Draw3(structures, resolution); - } + if (numStructures == 1) { + Draw1(structures, resolution); + } else if (numStructures == 2) { + Draw2(structures, resolution); + } else if (numStructures == 3) { + Draw3(structures, resolution); + } fl_font(priorFont, priorFontSize); } -void DiagramWindow::DrawKey3() -{ +void DiagramWindow::DrawKey3() { int yPosn = 55; char mystr[10] = ""; @@ -292,7 +296,7 @@ void DiagramWindow::DrawKey3() fl_rectf(m_menus[1]->x(), yPosn, m_menus[1]->w(), 3); fl_rectf(m_menus[2]->x(), yPosn, m_menus[2]->w(), 3); sprintf(mystr, "%d", numPairs[0]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn + 3); yPosn += 10; fl_color(FL_RED); @@ -301,7 +305,7 @@ void DiagramWindow::DrawKey3() fl_xyline(m_menus[1]->x(), yPosn, m_menus[1]->x() + m_menus[1]->w()); fl_xyline(m_menus[2]->x(), yPosn, m_menus[2]->x() + m_menus[2]->w()); sprintf(mystr, "%d", numPairs[1]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn + 3); yPosn += 10; fl_color(FL_GREEN); @@ -310,7 +314,7 @@ void DiagramWindow::DrawKey3() fl_xyline(m_menus[0]->x(), yPosn, m_menus[0]->x() + m_menus[0]->w()); fl_xyline(m_menus[2]->x(), yPosn, m_menus[2]->x() + m_menus[2]->w()); sprintf(mystr, "%d", numPairs[2]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn + 3); yPosn += 10; fl_color(FL_BLUE); @@ -319,17 +323,17 @@ void DiagramWindow::DrawKey3() fl_xyline(m_menus[0]->x(), yPosn, m_menus[0]->x() + m_menus[0]->w()); fl_xyline(m_menus[1]->x(), yPosn, m_menus[1]->x() + m_menus[1]->w()); sprintf(mystr, "%d", numPairs[6]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn + 3); yPosn += 10; //fl_color(FL_YELLOW); - fl_color(fl_rgb_color(255,200,0)); + fl_color(fl_rgb_color(255, 200, 0)); fl_rectf(m_menus[0]->x(), yPosn, m_menus[0]->w(), 3); fl_rectf(m_menus[1]->x(), yPosn, m_menus[1]->w(), 3); fl_line_style(FL_DOT); fl_xyline(m_menus[2]->x(), yPosn, m_menus[2]->x() + m_menus[2]->w()); sprintf(mystr, "%d", numPairs[3]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn + 3); yPosn += 10; fl_color(FL_MAGENTA); @@ -338,7 +342,7 @@ void DiagramWindow::DrawKey3() fl_line_style(FL_DOT); fl_xyline(m_menus[1]->x(), yPosn, m_menus[1]->x() + m_menus[1]->w()); sprintf(mystr, "%d", numPairs[4]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn + 3); yPosn += 10; fl_color(FL_CYAN); @@ -347,12 +351,11 @@ void DiagramWindow::DrawKey3() fl_line_style(FL_DOT); fl_xyline(m_menus[0]->x(), yPosn, m_menus[0]->x() + m_menus[0]->w()); sprintf(mystr, "%d", numPairs[5]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn+3); - + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn + 3); + } -void DiagramWindow::DrawKey2(const int a, const int b) -{ +void DiagramWindow::DrawKey2(const int a, const int b) { int yPosn = 55; char mystr[10] = ""; @@ -360,34 +363,120 @@ void DiagramWindow::DrawKey2(const int a, const int b) fl_rectf(m_menus[a]->x(), yPosn, m_menus[a]->w(), 3); fl_rectf(m_menus[b]->x(), yPosn, m_menus[b]->w(), 3); sprintf(mystr, "%d", numPairs[0]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn + 3); yPosn += 10; fl_color(FL_RED); fl_rectf(m_menus[a]->x(), yPosn, m_menus[a]->w(), 3); sprintf(mystr, "%d", numPairs[1]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 40, yPosn + 3); yPosn += 10; fl_color(FL_GREEN); fl_rectf(m_menus[b]->x(), yPosn, m_menus[b]->w(), 3); sprintf(mystr, "%d", numPairs[2]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn+3); - + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, yPosn + 3); + } -void DiagramWindow::DrawKey1(const int a) -{ +void DiagramWindow::DrawKey1(const int a) { fl_color(FL_BLACK); fl_rectf(m_menus[a]->x(), 55, m_menus[a]->w(), 3); - + char mystr[10] = ""; sprintf(mystr, "%d", numPairs[0]); - fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, 55+3); + fl_draw(mystr, m_menus[2]->x() + m_menus[2]->w() + 10, 55 + 3); } -void DiagramWindow::Draw3(RNAStructure** structures, const int resolution) -{ +// draws / masks the outer circle on the arcs created by Draw*(): +void DiagramWindow::CairoPrepareDisplay() { + cairo_push_group(crDraw); + cairo_set_source_rgb(crDraw, 1.0, 1.0, 1.0); + cairo_paint(crDraw); + cairo_arc(crDraw, IMAGE_WIDTH / 2, IMAGE_WIDTH / 2, 0.0, 0.0, 2.0 * M_PI); + cairo_set_source_rgba(crDraw, 0.4, 0.4, 0.4, 1.0); + cairo_fill(crDraw); + circleMask = cairo_pop_group(crDraw); + //cairo_pop_group_to_source(crDraw); + //cairo_push_group(crDraw); + cairo_set_source_rgba(crDraw, 1.0, 1.0, 1.0, 0.5); + cairo_paint(crDraw); + cairo_set_line_width(crDraw, MAX(1, pixelWidth)); +} + +void DiagramWindow::CairoBufferFinishingTouches() { + cairo_mask(crDraw, circleMask); +} + +void DiagramWindow::CairoDrawBufferToScreen() { + //m_glWindow->SetTextureData(cairo_image_surface_get_data(crSurface), IMAGE_WIDTH); + fl_draw_image(cairo_image_surface_get_data(crSurface), 0, 120, IMAGE_WIDTH, IMAGE_HEIGHT, + IMAGE_DEPTH, 0); +} + +void DiagramWindow::SetCairoBranchColor(const BranchID_t &branchType, int enabled, + CairoColorSpec_t fallbackColorFlag) { + + int nextColorFlag = fallbackColorFlag; + if (enabled && branchType != BRANCH_UNDEFINED) { + switch (branchType) { + case BRANCH1: + nextColorFlag = CR_BRANCH1; + break; + case BRANCH2: + nextColorFlag = CR_BRANCH2; + break; + case BRANCH3: + nextColorFlag = CR_BRANCH3; + break; + case BRANCH4: + nextColorFlag = CR_BRANCH4; + break; + default: + break; + } + } + switch (nextColorFlag) { + case CR_BLACK: + CairoSetRGB(0, 0, 0); + break; + case CR_RED: + CairoSetRGB(239, 41, 41); + break; + case CR_GREEN: + CairoSetRGB(78, 154, 6); + break; + case CR_BLUE: + CairoSetRGB(52, 101, 164); + break; + case CR_YELLOW: + CairoSetRGB(252, 233, 79); + break; + case CR_MAGENTA: + CairoSetRGB(255, 57, 225); + break; + case CR_CYAN: + CairoSetRGB(60, 208, 237); + break; + case CR_BRANCH1: + CairoSetRGB(92, 160, 215); + break; + case CR_BRANCH2: + CairoSetRGB(183, 127, 77); + break; + case CR_BRANCH3: + CairoSetRGB(243, 153, 193); + break; + case CR_BRANCH4: + CairoSetRGB(123, 204, 153); + break; + default: + break; + } + +} + +void DiagramWindow::Draw3(RNAStructure **structures, const int resolution) { float centerX = 0.0f; float centerY = 0.0f; float angleBase = 0.0f; @@ -395,134 +484,138 @@ void DiagramWindow::Draw3(RNAStructure** structures, const int resolution) float radius = 0.0f; unsigned int numBases = structures[0]->GetLength(); - ComputeDiagramParams(numBases, resolution, centerX, centerY, angleBase, - angleDelta, radius); - - for (unsigned int ui = 0; ui < numBases; ++ui) - { - const RNAStructure::BaseData* baseData1 = structures[0]->GetBaseAt(ui); - DrawBase(ui, baseData1->m_base, centerX, centerY, angleBase, angleDelta, - radius + 7.5f); - - const RNAStructure::BaseData* baseData2 = structures[1]->GetBaseAt(ui); - const RNAStructure::BaseData* baseData3 = structures[2]->GetBaseAt(ui); - - if (baseData1->m_pair != RNAStructure::UNPAIRED && - baseData1->m_pair > ui) - { - if (baseData1->m_pair == baseData2->m_pair) - { - if (baseData1->m_pair == baseData3->m_pair) - { + ComputeDiagramParams(numBases, resolution, centerX, centerY, angleBase, + angleDelta, radius); + + WarnUserDrawingConflict(); + + for (unsigned int ui = 0; ui < numBases; ++ui) { + const RNAStructure::BaseData *baseData1 = structures[0]->GetBaseAt(ui); + DrawBase(ui, baseData1->m_base, centerX, centerY, angleBase, angleDelta, + radius + 7.5f); + + const RNAStructure::BaseData *baseData2 = structures[1]->GetBaseAt(ui); + const RNAStructure::BaseData *baseData3 = structures[2]->GetBaseAt(ui); + + if (baseData1->m_pair != RNAStructure::UNPAIRED && + baseData1->m_pair > ui) { + if (baseData1->m_pair == baseData2->m_pair) { + if (baseData1->m_pair == baseData3->m_pair) { fl_color(FL_BLACK); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - else - { + SetCairoBranchColor(structures[0]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLACK); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } else { //fl_color(FL_YELLOW); - fl_color(fl_rgb_color(255,200,0)); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - - if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - fl_color(FL_BLUE); - DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } + fl_color(fl_rgb_color(255, 200, 0)); + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_YELLOW); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + + if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + fl_color(FL_BLUE); + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLUE); + DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } } - } - else if (baseData1->m_pair == baseData3->m_pair) - { + } else if (baseData1->m_pair == baseData3->m_pair) { fl_color(FL_MAGENTA); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - - if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - fl_color(FL_GREEN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - } - else - { + SetCairoBranchColor(structures[0]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_MAGENTA); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + + if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + fl_color(FL_GREEN); + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_GREEN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } + } else { fl_color(FL_RED); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - - if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - if (baseData2->m_pair == baseData3->m_pair) - { - fl_color(FL_CYAN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - else - { - fl_color(FL_GREEN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - - if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - fl_color(FL_BLUE); - DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - } - } - else if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - fl_color(FL_BLUE); - DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_RED); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + + if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + if (baseData2->m_pair == baseData3->m_pair) { + fl_color(FL_CYAN); + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_CYAN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } else { + fl_color(FL_GREEN); + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_GREEN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + + if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + fl_color(FL_BLUE); + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLUE); + DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } + } + } else if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + fl_color(FL_BLUE); + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLUE); + DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } } - } - else if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - if (baseData2->m_pair == baseData3->m_pair) - { + } else if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + if (baseData2->m_pair == baseData3->m_pair) { fl_color(FL_CYAN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - else - { + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_CYAN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } else { fl_color(FL_GREEN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - - if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - fl_color(FL_BLUE); - DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_GREEN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + + if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + fl_color(FL_BLUE); + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLUE); + DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } } - } - else if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { + } else if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { fl_color(FL_BLUE); - DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, - angleDelta, radius); + SetCairoBranchColor(structures[2]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLUE); + DrawArc(ui, baseData3->m_pair, centerX, centerY, angleBase, + angleDelta, radius); } } + CairoBufferFinishingTouches(); + CairoDrawBufferToScreen(); } -void DiagramWindow::Draw2(RNAStructure** structures, const int resolution) -{ +void DiagramWindow::Draw2(RNAStructure **structures, const int resolution) { float centerX = 0.0f; float centerY = 0.0f; float angleBase = 0.0f; @@ -530,52 +623,54 @@ void DiagramWindow::Draw2(RNAStructure** structures, const int resolution) float radius = 0.0f; unsigned int numBases = structures[0]->GetLength(); - ComputeDiagramParams(numBases, resolution, centerX, centerY, angleBase, - angleDelta, radius); - - for (unsigned int ui = 0; ui < numBases; ++ui) - { - const RNAStructure::BaseData* baseData1 = structures[0]->GetBaseAt(ui); - DrawBase(ui, baseData1->m_base, centerX, centerY, angleBase, angleDelta, - radius + 7.5f); - - const RNAStructure::BaseData* baseData2 = structures[1]->GetBaseAt(ui); - if (baseData1->m_pair != RNAStructure::UNPAIRED - && baseData1->m_pair > ui) - { - if (baseData1->m_pair == baseData2->m_pair) - { - fl_color(FL_BLACK); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - else - { - fl_color(FL_RED); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - - if (baseData2->m_pair != - RNAStructure::UNPAIRED && baseData2->m_pair > ui) - { - fl_color(FL_GREEN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } - } - } - else if (baseData2->m_pair != - RNAStructure::UNPAIRED && baseData2->m_pair > ui) - { - fl_color(FL_GREEN); - DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - } + ComputeDiagramParams(numBases, resolution, centerX, centerY, angleBase, + angleDelta, radius); + WarnUserDrawingConflict(); + + for (unsigned int ui = 0; ui < numBases; ++ui) { + const RNAStructure::BaseData *baseData1 = structures[0]->GetBaseAt(ui); + DrawBase(ui, baseData1->m_base, centerX, centerY, angleBase, angleDelta, + radius + 7.5f); + + const RNAStructure::BaseData *baseData2 = structures[1]->GetBaseAt(ui); + if (baseData1->m_pair != RNAStructure::UNPAIRED + && baseData1->m_pair > ui) { + if (baseData1->m_pair == baseData2->m_pair) { + fl_color(FL_BLACK); + SetCairoBranchColor(structures[0]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLACK); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } else { + fl_color(FL_RED); + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_RED); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + + if (baseData2->m_pair != + RNAStructure::UNPAIRED && baseData2->m_pair > ui) { + fl_color(FL_GREEN); + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_GREEN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } + } + } else if (baseData2->m_pair != + RNAStructure::UNPAIRED && baseData2->m_pair > ui) { + fl_color(FL_GREEN); + SetCairoBranchColor(structures[1]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_GREEN); + DrawArc(ui, baseData2->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + } } + CairoBufferFinishingTouches(); + CairoDrawBufferToScreen(); } -void DiagramWindow::Draw1(RNAStructure** structures, const int resolution) -{ +void DiagramWindow::Draw1(RNAStructure **structures, const int resolution) { float centerX = 0.0f; float centerY = 0.0f; float angleBase = 0.0f; @@ -584,82 +679,71 @@ void DiagramWindow::Draw1(RNAStructure** structures, const int resolution) int counter = 0; unsigned int numBases = structures[0]->GetLength(); - ComputeDiagramParams(numBases, resolution, centerX, centerY, angleBase, - angleDelta, radius); - - for (unsigned int ui = 0; ui < numBases; ++ui) - { - const RNAStructure::BaseData* baseData1 = structures[0]->GetBaseAt(ui); - DrawBase(ui, baseData1->m_base, centerX, centerY, angleBase, angleDelta, - radius + 7.5f); - - if (baseData1->m_pair != RNAStructure::UNPAIRED - && baseData1->m_pair > ui) - { - fl_color(FL_BLACK); - DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, - angleDelta, radius); - counter++; - } + ComputeDiagramParams(numBases, resolution, centerX, centerY, angleBase, + angleDelta, radius); + + for (unsigned int ui = 0; ui < numBases; ++ui) { + const RNAStructure::BaseData *baseData1 = structures[0]->GetBaseAt(ui); + DrawBase(ui, baseData1->m_base, centerX, centerY, angleBase, angleDelta, + radius + 7.5f); + + if (baseData1->m_pair != RNAStructure::UNPAIRED + && baseData1->m_pair > ui) { + fl_color(FL_BLACK); + SetCairoBranchColor(structures[0]->GetBranchTypeAt(ui)->getBranchID(), + (int) m_drawBranchesIndicator->value(), CR_BLACK); + DrawArc(ui, baseData1->m_pair, centerX, centerY, angleBase, + angleDelta, radius); + counter++; + } } + + //CairoBufferFinishingTouches(); + CairoDrawBufferToScreen(); + } -void DiagramWindow::ComputeNumPairs(RNAStructure** structures, - int numStructures) -{ +void DiagramWindow::ComputeNumPairs(RNAStructure **structures, + int numStructures) { unsigned int numBases = structures[0]->GetLength(); - if(numStructures == 1) - { + if (numStructures == 1) { unsigned int counter1 = 0; - for(unsigned int ui = 0; ui < numBases; ++ui) - { - const RNAStructure::BaseData* baseData1 = - structures[0]->GetBaseAt(ui); - if(baseData1->m_pair != RNAStructure::UNPAIRED && - baseData1->m_pair > ui) + for (unsigned int ui = 0; ui < numBases; ++ui) { + const RNAStructure::BaseData *baseData1 = + structures[0]->GetBaseAt(ui); + if (baseData1->m_pair != RNAStructure::UNPAIRED && + baseData1->m_pair > ui) counter1++; } numPairs[0] = counter1; - } - else if(numStructures == 2) - { + } else if (numStructures == 2) { unsigned int counter1 = 0; //black unsigned int counter2 = 0; //red unsigned int counter3 = 0; //green - for (unsigned int ui = 0; ui < numBases; ++ui) - { - const RNAStructure::BaseData* baseData1 = structures[0]->GetBaseAt(ui); - const RNAStructure::BaseData* baseData2 = structures[1]->GetBaseAt(ui); - if (baseData1->m_pair != RNAStructure::UNPAIRED && - baseData1->m_pair > ui) - { - if (baseData1->m_pair == baseData2->m_pair) - { + for (unsigned int ui = 0; ui < numBases; ++ui) { + const RNAStructure::BaseData *baseData1 = structures[0]->GetBaseAt(ui); + const RNAStructure::BaseData *baseData2 = structures[1]->GetBaseAt(ui); + if (baseData1->m_pair != RNAStructure::UNPAIRED && + baseData1->m_pair > ui) { + if (baseData1->m_pair == baseData2->m_pair) { counter1++; - } - else - { - if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - counter3++; - } + } else { + if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + counter3++; + } counter2++; } - } - else if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { + } else if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { counter3++; } } numPairs[0] = counter1; numPairs[1] = counter2; numPairs[2] = counter3; - } - else if(numStructures == 3) - { + } else if (numStructures == 3) { unsigned int counter1 = 0; //black = in all 3 structures unsigned int counter2 = 0; //red = in only structure 1 unsigned int counter3 = 0; //green = in only structure 2 @@ -667,91 +751,64 @@ void DiagramWindow::ComputeNumPairs(RNAStructure** structures, unsigned int counter5 = 0; //magenta = in structures 1 & 3 unsigned int counter6 = 0; //cyan = in structures 2 & 3 unsigned int counter7 = 0; //blue = in only structure 3 - for (unsigned int ui = 0; ui < numBases; ++ui) - { - const RNAStructure::BaseData* baseData1 = structures[0]->GetBaseAt(ui); - const RNAStructure::BaseData* baseData2 = structures[1]->GetBaseAt(ui); - const RNAStructure::BaseData* baseData3 = structures[2]->GetBaseAt(ui); - if (baseData1->m_pair != RNAStructure::UNPAIRED && - baseData1->m_pair > ui) - { - if (baseData1->m_pair == baseData2->m_pair) - { - if (baseData1->m_pair == baseData3->m_pair) - { + for (unsigned int ui = 0; ui < numBases; ++ui) { + const RNAStructure::BaseData *baseData1 = structures[0]->GetBaseAt(ui); + const RNAStructure::BaseData *baseData2 = structures[1]->GetBaseAt(ui); + const RNAStructure::BaseData *baseData3 = structures[2]->GetBaseAt(ui); + if (baseData1->m_pair != RNAStructure::UNPAIRED && + baseData1->m_pair > ui) { + if (baseData1->m_pair == baseData2->m_pair) { + if (baseData1->m_pair == baseData3->m_pair) { counter1++; - } - else - { + } else { counter4++; - - if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - counter7++; - } + + if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + counter7++; + } } - } - else if (baseData1->m_pair == baseData3->m_pair) - { + } else if (baseData1->m_pair == baseData3->m_pair) { counter5++; - - if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - counter3++; - } - } - else - { + + if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + counter3++; + } + } else { counter2++; - - if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - if (baseData2->m_pair == baseData3->m_pair) - { - counter6++; - } - else - { - counter3++; - - if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - counter7++; - } - } - } - else if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - counter7++; - } + + if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + if (baseData2->m_pair == baseData3->m_pair) { + counter6++; + } else { + counter3++; + + if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + counter7++; + } + } + } else if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + counter7++; + } } - } - else if (baseData2->m_pair != RNAStructure::UNPAIRED && - baseData2->m_pair > ui) - { - if (baseData2->m_pair == baseData3->m_pair) - { + } else if (baseData2->m_pair != RNAStructure::UNPAIRED && + baseData2->m_pair > ui) { + if (baseData2->m_pair == baseData3->m_pair) { counter6++; - } - else - { + } else { counter3++; - - if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { - counter7++; - } + + if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { + counter7++; + } } - } - else if (baseData3->m_pair != RNAStructure::UNPAIRED && - baseData3->m_pair > ui) - { + } else if (baseData3->m_pair != RNAStructure::UNPAIRED && + baseData3->m_pair > ui) { counter7++; } } @@ -766,50 +823,47 @@ void DiagramWindow::ComputeNumPairs(RNAStructure** structures, } void DiagramWindow::ComputeCircle( - const float& x1, - const float& y1, - const float& x2, - const float& y2, - const float& x3, - const float& y3, - double& cX, - double& cY, - double& r) -{ + const float &x1, + const float &y1, + const float &x2, + const float &y2, + const float &x3, + const float &y3, + double &cX, + double &cY, + double &r) { double denom = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - y2 * x3; - if (denom < 0.001) - { - cX = cY = 0.0f; - r = 0.0f; + if (denom < 0.001) { + cX = cY = 0.0f; + r = 0.0f; } double sq1 = x1 * x1 + y1 * y1; double sq2 = x2 * x2 + y2 * y2; double sq3 = x3 * x3 + y3 * y3; - cX = (sq1 * (y2 - y3) - y1 * (sq2 - sq3) + sq2 * y3 - y2 * sq3) / (2.0 * - denom); - cY = (x1 * (sq2 - sq3) - sq1 * (x2 - x3) + sq3 * x2 - x3 * sq2) / (2.0 * - denom); + cX = (sq1 * (y2 - y3) - y1 * (sq2 - sq3) + sq2 * y3 - y2 * sq3) / (2.0 * + denom); + cY = (x1 * (sq2 - sq3) - sq1 * (x2 - x3) + sq3 * x2 - x3 * sq2) / (2.0 * + denom); r = sqrt((x1 - cX) * (x1 - cX) + (y1 - cY) * (y1 - cY)); } void DiagramWindow::DrawArc( - const unsigned int b1, - const unsigned int b2, - const float centerX, - const float centerY, - const float angleBase, - const float angleDelta, - const float radius) -{ - float angle1 = angleBase - (float)b1 * angleDelta; + const unsigned int b1, + const unsigned int b2, + const float centerX, + const float centerY, + const float angleBase, + const float angleDelta, + const float radius) { + float angle1 = angleBase - (float) b1 * angleDelta; float xPosn1 = centerX + cos(angle1) * radius; float yPosn1 = centerY - sin(angle1) * radius; - float angle2 = angleBase - (float)b2 * angleDelta; + float angle2 = angleBase - (float) b2 * angleDelta; float xPosn2 = centerX + cos(angle2) * radius; float yPosn2 = centerY - sin(angle2) * radius; @@ -822,129 +876,126 @@ void DiagramWindow::DrawArc( double arcX = 0.0f; double arcY = 0.0f; double arcR = 0.0f; - ComputeCircle(xPosn1, yPosn1, xPosn2, yPosn2, xPosn3, yPosn3, arcX, arcY, - arcR); + ComputeCircle(xPosn1, yPosn1, xPosn2, yPosn2, xPosn3, yPosn3, arcX, arcY, + arcR); - int boundX = (int)(arcX - arcR); - int boundY = (int)(arcY - arcR); - int boundSize = (int)(2.0f * arcR); + int boundX = (int) (arcX - arcR); + int boundY = (int) (arcY - arcR); + int boundSize = (int) (2.0f * arcR); double arc1 = 180.0 / M_PI * atan2(arcY - yPosn1, xPosn1 - arcX); double arc2 = 180.0 / M_PI * atan2(arcY - yPosn2, xPosn2 - arcX); + int boundingBoxCenterX = boundX + boundSize / 2; + int boundingBoxCenterY = boundY + boundSize / 2; + float boundingBoxRadius = boundSize / 2.0; + if (arc2 - arc1 > 180.0) - arc1 += 360.0; + arc1 += 360.0; if (arc1 - arc2 > 180.0) - arc2 += 360.0; - if (arc2 > arc1) - { - fl_arc(boundX, boundY, boundSize, boundSize, arc1, arc2); - if (pixelWidth > 1) - fl_arc(boundX+1,boundY+1,boundSize,boundSize,arc1,arc2); - if (pixelWidth > 2) - fl_arc(boundX+1,boundY,boundSize,boundSize,arc1,arc2); + arc2 += 360.0; + if (arc2 > arc1) { + //fl_arc(boundX, boundY, boundSize, boundSize, arc1, arc2); + //if (pixelWidth > 1) + // fl_arc(boundX+1,boundY+1,boundSize,boundSize,arc1,arc2); + //if (pixelWidth > 2) + // fl_arc(boundX+1,boundY,boundSize,boundSize,arc1,arc2); + cairo_arc(crDraw, boundingBoxCenterX, boundingBoxCenterY, boundingBoxRadius, arc1, arc2); + } else { + //fl_arc(boundX, boundY, boundSize, boundSize, arc2, arc1); + //if (pixelWidth > 1) + // fl_arc(boundX+1, boundY+1, boundSize, boundSize, arc2, arc1); + //if (pixelWidth > 2) + // fl_arc(boundX+1, boundY, boundSize, boundSize, arc2, arc1); + cairo_arc(crDraw, boundingBoxCenterX, boundingBoxCenterY, boundingBoxRadius, arc2, arc1); } - else - { - fl_arc(boundX, boundY, boundSize, boundSize, arc2, arc1); - if (pixelWidth > 1) - fl_arc(boundX+1, boundY+1, boundSize, boundSize, arc2, arc1); - if (pixelWidth > 2) - fl_arc(boundX+1, boundY, boundSize, boundSize, arc2, arc1); - } - + cairo_close_path(crDraw); + cairo_stroke_preserve(crDraw); + //cairo_move_to (crDraw, 0, 0); + //cairo_line_to (crDraw, 10, 10); + //cairo_stroke (crDraw); } void DiagramWindow::DrawBase( - const unsigned int index, - const RNAStructure::Base base, - const float centerX, - const float centerY, - const float angleBase, - const float angleDelta, - const float radius) -{ - float angle1 = angleBase - (float)index * angleDelta; + const unsigned int index, + const RNAStructure::Base base, + const float centerX, + const float centerY, + const float angleBase, + const float angleDelta, + const float radius) { + float angle1 = angleBase - (float) index * angleDelta; float xPosn1 = centerX + cos(angle1) * radius; - float yPosn1 = centerY - sin(angle1) * radius - fl_descent() + 0.5 * - fl_height(); + float yPosn1 = centerY - sin(angle1) * radius - fl_descent() + 0.5 * + fl_height(); //fl_color(128, 128, 128); - fl_color(FL_WHITE); - switch (base) - { - case RNAStructure::A: - fl_draw("A", (int)(xPosn1 - fl_width('A') * 0.5f), (int)yPosn1); - break; - case RNAStructure::C: - fl_draw("C", (int)(xPosn1 - fl_width('C') * 0.5f), (int)yPosn1); - break; - case RNAStructure::G: - fl_draw("G", (int)(xPosn1 - fl_width('G') * 0.5f), (int)yPosn1); - break; - case RNAStructure::U: - fl_draw("U", (int)(xPosn1 - fl_width('U') * 0.5f), (int)yPosn1); - break; + fl_color(FL_WHITE); + switch (base) { + case RNAStructure::A: + fl_draw("A", (int) (xPosn1 - fl_width('A') * 0.5f), (int) yPosn1); + break; + case RNAStructure::C: + fl_draw("C", (int) (xPosn1 - fl_width('C') * 0.5f), (int) yPosn1); + break; + case RNAStructure::G: + fl_draw("G", (int) (xPosn1 - fl_width('G') * 0.5f), (int) yPosn1); + break; + case RNAStructure::U: + fl_draw("U", (int) (xPosn1 - fl_width('U') * 0.5f), (int) yPosn1); + break; } } void DiagramWindow::ComputeDiagramParams( - const int numBases, - const int resolution, - float& centerX, - float& centerY, - float& angleBase, - float& angleDelta, - float& radius) -{ - angleDelta = (M_PI * 2.0f - 0.05f) / (float)numBases; + const int numBases, + const int resolution, + float ¢erX, + float ¢erY, + float &angleBase, + float &angleDelta, + float &radius) { + angleDelta = (M_PI * 2.0f - 0.05f) / (float) numBases; angleBase = 1.5f * M_PI - 0.025f; - centerX = (float)resolution / 2.0f; - centerY = (float)resolution / 2.0f; + centerX = (float) resolution / 2.0f; + centerY = (float) resolution / 2.0f; radius = centerX < centerY ? centerX - 15.f : centerY - 15.f; } -void DiagramWindow::AddStructure(const int index) -{ - if (std::find(m_structures.begin(), m_structures.end(), index) == - m_structures.end()) - { - m_structures.push_back(index); - RebuildMenus(); - redraw(); +void DiagramWindow::AddStructure(const int index) { + if (std::find(m_structures.begin(), m_structures.end(), index) == + m_structures.end()) { + m_structures.push_back(index); + RebuildMenus(); + redraw(); } } -void DiagramWindow::RemoveStructure(const int index) -{ - std::vector::iterator iter = std::find(m_structures.begin(), - m_structures.end(), index); - - if (iter != m_structures.end()) - { - m_structures.erase(iter); - - intptr_t user_data0 = (intptr_t)(m_menuItems[m_menus[0]->value()].user_data()); - intptr_t user_data1 = (intptr_t)(m_menuItems[m_menus[1]->value()].user_data()); - intptr_t user_data2 = (intptr_t)(m_menuItems[m_menus[2]->value()].user_data()); - - RebuildMenus(); - - if ((intptr_t)(m_menuItems[m_menus[0]->value()].user_data()) != user_data0 - || (intptr_t)(m_menuItems[m_menus[1]->value()].user_data()) != user_data1 - || (intptr_t)(m_menuItems[m_menus[2]->value()].user_data()) != user_data2) - { - m_redrawStructures = true; - } - redraw(); +void DiagramWindow::RemoveStructure(const int index) { + std::vector::iterator iter = std::find(m_structures.begin(), + m_structures.end(), index); + + if (iter != m_structures.end()) { + m_structures.erase(iter); + + intptr_t user_data0 = (intptr_t) (m_menuItems[m_menus[0]->value()].user_data()); + intptr_t user_data1 = (intptr_t) (m_menuItems[m_menus[1]->value()].user_data()); + intptr_t user_data2 = (intptr_t) (m_menuItems[m_menus[2]->value()].user_data()); + + RebuildMenus(); + + if ((intptr_t) (m_menuItems[m_menus[0]->value()].user_data()) != user_data0 + || (intptr_t) (m_menuItems[m_menus[1]->value()].user_data()) != user_data1 + || (intptr_t) (m_menuItems[m_menus[2]->value()].user_data()) != user_data2) { + m_redrawStructures = true; + } + redraw(); } } -void DiagramWindow::SetStructures(const std::vector& structures) -{ +void DiagramWindow::SetStructures(const std::vector &structures) { m_structures.clear(); - for (unsigned int ui = 0; ui < structures.size(); ++ui) - { + for (unsigned int ui = 0; ui < structures.size(); ++ui) { m_structures.push_back(structures[ui]); } @@ -952,115 +1003,139 @@ void DiagramWindow::SetStructures(const std::vector& structures) redraw(); } -void DiagramWindow::RebuildMenus() -{ +void DiagramWindow::RebuildMenus() { // Create the menus, if they don't already exist. int activeMenuIndex[3]; bool activeSet[3]; - if (!m_menus[0]) - { - this->begin(); - - Fl_Box* label = new Fl_Box(ms_menu_minx[0], 0, ms_menu_width, 25, - "Structure 1"); - label->labelcolor(FL_BLACK); - label = new Fl_Box(ms_menu_minx[1],0,ms_menu_width,25,"Structure 2"); - label->labelcolor(FL_BLACK); - label = new Fl_Box(ms_menu_minx[2],0,ms_menu_width,25,"Structure 3"); - label->labelcolor(FL_BLACK); - m_menus[0] = new Fl_Choice(ms_menu_minx[0], 25, ms_menu_width, 25); - m_menus[1] = new Fl_Choice(ms_menu_minx[1], 25, ms_menu_width, 25); - m_menus[2] = new Fl_Choice(ms_menu_minx[2], 25, ms_menu_width, 25); - m_menus[0]->callback(MenuCallback); - m_menus[1]->callback(MenuCallback); - m_menus[2]->callback(MenuCallback); - activeMenuIndex[0] = -1; - activeMenuIndex[1] = -1; - activeMenuIndex[2] = -1; - activeSet[0] = false; - activeSet[1] = false; - activeSet[2] = false; - - this->end(); - } - else - { - // Cache the current active index, if any - for (int j = 0; j < 3; ++j) - { - activeMenuIndex[j] = (intptr_t)m_menus[j]->mvalue()->user_data(); - activeSet[j] = false; - } + if (!m_menus[0]) { + this->begin(); + + Fl_Box *label = new Fl_Box(ms_menu_minx[0], 0, ms_menu_width, 25, + "Structure 1"); + label->labelcolor(FL_BLACK); + label = new Fl_Box(ms_menu_minx[1], 0, ms_menu_width, 25, "Structure 2"); + label->labelcolor(FL_BLACK); + label = new Fl_Box(ms_menu_minx[2], 0, ms_menu_width, 25, "Structure 3"); + label->labelcolor(FL_BLACK); + m_menus[0] = new Fl_Choice(ms_menu_minx[0], 25, ms_menu_width, 25); + m_menus[1] = new Fl_Choice(ms_menu_minx[1], 25, ms_menu_width, 25); + m_menus[2] = new Fl_Choice(ms_menu_minx[2], 25, ms_menu_width, 25); + m_menus[0]->callback(MenuCallback); + m_menus[1]->callback(MenuCallback); + m_menus[2]->callback(MenuCallback); + activeMenuIndex[0] = -1; + activeMenuIndex[1] = -1; + activeMenuIndex[2] = -1; + activeSet[0] = false; + activeSet[1] = false; + activeSet[2] = false; + + int horizCheckBoxPos = ms_menu_minx[2] + ms_menu_width + 125; + m_drawBranchesIndicator = new Fl_Check_Button(horizCheckBoxPos, 5, 20, 20, + "Draw (16S) Domains"); + m_drawBranchesIndicator->callback(checkBoxChangedStateCallback, m_drawBranchesIndicator); + m_drawBranchesIndicator->tooltip( + "Set whether to color code the four domains in 16S structures?"); + + exportButton = new Fl_Button(horizCheckBoxPos, 35, 125, 25, "Export PNG"); + exportButton->type(FL_NORMAL_BUTTON); + exportButton->callback(exportToPNGButtonPressHandler, exportButton); + + this->end(); + } else { + // Cache the current active index, if any + for (int j = 0; j < 3; ++j) { + activeMenuIndex[j] = (intptr_t) m_menus[j]->mvalue()->user_data(); + activeSet[j] = false; + } } - + // Remove any unnecessary menu items - for (int i = m_structures.size() + 1; i < m_menuItemsSize; ++i) - { - m_menuItems[i].label(0); + for (int i = m_structures.size() + 1; i < m_menuItemsSize; ++i) { + m_menuItems[i].label(0); } // Reallocate if necessary - if ((int)m_structures.size() + 2 > m_menuItemsSize) - { - m_menuItemsSize = m_structures.size() + 2; - free(m_menuItems); - m_menuItems = (Fl_Menu_Item*)malloc(sizeof(Fl_Menu_Item)*m_menuItemsSize); - m_menuItems[0].label("None"); - m_menuItems[0].shortcut(0); - m_menuItems[0].user_data((void*)-1); - - for (int i = 0; i < m_menuItemsSize; ++i) - { - m_menuItems[i].callback((Fl_Callback*)0); - m_menuItems[i].labeltype(FL_NORMAL_LABEL); - m_menuItems[i].labelsize(m_menus[0]->textsize()); - m_menuItems[i].labelcolor(FL_BLACK); - m_menuItems[i].labelfont(m_menus[0]->textfont()); - m_menuItems[i].flags = 0; - } - - m_menus[0]->menu(m_menuItems); - m_menus[1]->menu(m_menuItems); - m_menus[2]->menu(m_menuItems); + if ((int) m_structures.size() + 2 > m_menuItemsSize) { + m_menuItemsSize = m_structures.size() + 2; + free(m_menuItems); + m_menuItems = (Fl_Menu_Item *) malloc(sizeof(Fl_Menu_Item) * m_menuItemsSize); + m_menuItems[0].label("None"); + m_menuItems[0].shortcut(0); + m_menuItems[0].user_data((void *) -1); + + for (int i = 0; i < m_menuItemsSize; ++i) { + m_menuItems[i].callback((Fl_Callback *) 0); + m_menuItems[i].labeltype(FL_NORMAL_LABEL); + m_menuItems[i].labelsize(m_menus[0]->textsize()); + m_menuItems[i].labelcolor(FL_BLACK); + m_menuItems[i].labelfont(m_menus[0]->textfont()); + m_menuItems[i].flags = 0; + } + + m_menus[0]->menu(m_menuItems); + m_menus[1]->menu(m_menuItems); + m_menus[2]->menu(m_menuItems); } // Add entries - StructureManager* structureManager = - RNAStructViz::GetInstance()->GetStructureManager(); - for (unsigned int ui = 0; ui < m_structures.size(); ++ui) - { - RNAStructure* structure = structureManager->GetStructure(m_structures[ui]); - - m_menuItems[ui + 1].label(structure->GetFilename()); - m_menuItems[ui + 1].user_data((void*)m_structures[ui]); - m_menuItems[ui + 1].shortcut(0); - - for (int j = 0; j < 3; ++j) - { - if (activeMenuIndex[j] == m_structures[ui]) - { - m_menus[j]->value(ui + 1); - activeSet[j] = true; - } - } + StructureManager *structureManager = + RNAStructViz::GetInstance()->GetStructureManager(); + for (unsigned int ui = 0; ui < m_structures.size(); ++ui) { + RNAStructure *structure = structureManager->GetStructure(m_structures[ui]); + + m_menuItems[ui + 1].label(structure->GetFilename()); + m_menuItems[ui + 1].user_data((void *) m_structures[ui]); + m_menuItems[ui + 1].shortcut(0); + + for (int j = 0; j < 3; ++j) { + if (activeMenuIndex[j] == m_structures[ui]) { + m_menus[j]->value(ui + 1); + activeSet[j] = true; + } + } } // Reset active entries that have not already been set, and set the last // entry to NULL label m_menuItems[m_structures.size() + 1].label(0); - for (int j = 0; j < 3; ++j) - { - if (!activeSet[j]) - { - m_menus[j]->value(m_menuItems); - } + for (int j = 0; j < 3; ++j) { + if (!activeSet[j]) { + m_menus[j]->value(m_menuItems); + } } } -void DiagramWindow::MenuCallback(Fl_Widget* widget, void* userData) -{ - DiagramWindow* window = (DiagramWindow*)widget->parent(); +void DiagramWindow::MenuCallback(Fl_Widget *widget, void *userData) { + DiagramWindow *window = (DiagramWindow *) widget->parent(); window->m_redrawStructures = true; window->redraw(); } +void DiagramWindow::WarnUserDrawingConflict() { + if (!userConflictAlerted && m_drawBranchesIndicator->value()) { + int turnOff = fl_ask( + "You are attempting to draw multiple structures with distinct branch coding enabled. \nWe recommend against this due to readability concerns! \nDo you want to turn off branch / domain color coding now?"); + if (turnOff) { + m_drawBranchesIndicator->value(0); + } + userConflictAlerted = true; + } +} + +void DiagramWindow::CairoSetRGB(unsigned short R, unsigned short G, unsigned short B) { + fprintf(stderr, "(%g, %g, %g)\n", R / 255.0, G / 255.0, B / 255.0); + cairo_set_source_rgb(crDraw, R / 255.0, G / 255.0, B / 255.0); +} + +char *DiagramWindow::GetExportPNGFilePath() { + const char *chooserMsg = "Choose a file name for your PNG output image"; + const char *fileExtMask = "*.png"; + time_t currentTime = time(NULL); + struct tm *tmCurrentTime = localtime(¤tTime); + char defaultFilePath[256]; + strftime(defaultFilePath, 255, "RNAStructViz-GUIView-%F-%H%M%S.png", tmCurrentTime); + int pathNameType = 1; // 0 (absolute), otherise (relative) + return fl_file_chooser(chooserMsg, fileExtMask, defaultFilePath, pathNameType); +} + diff --git a/src/DiagramWindow.h b/src/DiagramWindow.h index 15b887c..81659c0 100755 --- a/src/DiagramWindow.h +++ b/src/DiagramWindow.h @@ -6,12 +6,35 @@ #define DIAGRAMWINDOW_H #include +#include #include +#include +#include #include +#include #include #include "GLWindow.h" #include "RNAStructure.h" +#include "BranchTypeIdentification.h" + +#define IMAGE_WIDTH (2048) +#define IMAGE_HEIGHT (2048) +#define IMAGE_DEPTH (3) + +typedef enum { + CR_BLACK = 0, + CR_RED = 1, + CR_GREEN = 2, + CR_BLUE = 3, + CR_YELLOW = 4, + CR_MAGENTA = 5, + CR_CYAN = 6, + CR_BRANCH1 = 7, + CR_BRANCH2 = 8, + CR_BRANCH3 = 9, + CR_BRANCH4 = 10 +} CairoColorSpec_t; class DiagramWindow : public Fl_Window { @@ -31,7 +54,7 @@ class DiagramWindow : public Fl_Window void RemoveStructure(const int index); void SetStructures(const std::vector& structures); - void ResetWindow(); + void ResetWindow(bool resetMenus); inline int GetFolderIndex() { @@ -41,11 +64,15 @@ class DiagramWindow : public Fl_Window void SetFolderIndex(int index); protected: + + static void checkBoxChangedStateCallback(Fl_Widget*, void *v); + static void exportToPNGButtonPressHandler(Fl_Widget*, void *v); + /* Draws the contents of the window. */ void draw(); - + void resize(int x, int y, int w, int h); private: @@ -62,6 +89,11 @@ class DiagramWindow : public Fl_Window void DrawKey3(); // if 3 structures are selected void DrawKey2(const int a, const int b); // if 2 selected structures void DrawKey1(const int a); // if 1 selected structure + + void CairoPrepareDisplay(); + void CairoBufferFinishingTouches(); + void CairoDrawBufferToScreen(); + void SetCairoBranchColor(const BranchID_t &branchType, int enabled, CairoColorSpec_t fallbackColorFlag); /* Draws the arcs for all the base pairs, colored according to their corresponding structures */ @@ -119,17 +151,27 @@ class DiagramWindow : public Fl_Window std::vector m_structures; Fl_Choice* m_menus[3]; + Fl_Check_Button *m_drawBranchesIndicator; + Fl_Button *exportButton; Fl_Menu_Item* m_menuItems; int m_menuItemsSize; GLWindow* m_glWindow; Fl_Offscreen m_offscreenImage[2]; uchar* m_imageData[2]; + cairo_surface_t *crSurface; + cairo_t *crDraw; + cairo_pattern_t *circleMask; bool m_redrawStructures; int numPairs[7]; int folderIndex; int pixelWidth; + bool userConflictAlerted; + + void WarnUserDrawingConflict(); + void CairoSetRGB(unsigned short R, unsigned short G, unsigned short B); + char * GetExportPNGFilePath(); }; diff --git a/src/RNAStructViz.cpp b/src/RNAStructViz.cpp index 5fb3c4a..0644ed1 100755 --- a/src/RNAStructViz.cpp +++ b/src/RNAStructViz.cpp @@ -79,7 +79,7 @@ void RNAStructViz::AddDiagramWindow(int index) { diagram->SetStructures(structures); diagram->SetFolderIndex(index); - diagram->ResetWindow(); + diagram->ResetWindow(true); diagram->show(); return; } diff --git a/src/RNAStructure.cpp b/src/RNAStructure.cpp index 34204f7..e8deaa4 100755 --- a/src/RNAStructure.cpp +++ b/src/RNAStructure.cpp @@ -1,9 +1,8 @@ #include "RNAStructure.h" +#include "BranchTypeIdentification.h" +#include #include #include -#include -#include -#include #include #include @@ -12,19 +11,32 @@ const unsigned int RNAStructure::UNPAIRED = ~0x0; RNAStructure::RNAStructure() : m_sequenceLength(0) , m_sequence(0) - , m_contentWindow(0) , m_displayString(0) { + branchType = NULL; //new RNABranchType_t(BRANCH_UNDEFINED, NULL); +} + +RNAStructure::RNAStructure(const RNAStructure &rnaStruct) { + copyRNAStructure(rnaStruct); +} + +RNAStructure & RNAStructure::operator=(const RNAStructure &rhs) { + if(this != &rhs) { + copyRNAStructure(rhs); + } + return *this; +} + +void RNAStructure::copyRNAStructure(const RNAStructure &rnaStruct) { + // free the memory in the existing object: + //if(branchType != NULL) + // delete branchType; + fprintf(stderr, "TODO: NOT YET IMPLEMENTED!!\n"); } RNAStructure::~RNAStructure() { - if (m_contentWindow) - { - Fl::delete_widget(m_contentWindow); - } - free(m_displayString); //m_displayString = NULL; free(m_sequence); //m_sequence = NULL; @@ -35,16 +47,33 @@ RNAStructure::~RNAStructure() free(m_pathname); //m_pathname = NULL; } + + if(branchType != NULL) { + delete branchType; + branchType = NULL; + } + } RNAStructure::BaseData* RNAStructure::GetBaseAt(unsigned int position) { if (position < m_sequenceLength) { - return m_sequence + position; - } + //return m_sequence + position; + return &m_sequence[position]; + } + fprintf(stderr, "in GetBaseAt: m_sequenceLength=%d, position=%d\n", m_sequenceLength, position); + return NULL; +} - return 0; +RNABranchType_t* RNAStructure::GetBranchTypeAt(unsigned int position) +{ + if (position < m_sequenceLength) + { + //return branchType + position; + return &branchType[position]; + } + return NULL; } RNAStructure* RNAStructure::CreateFromFile(const char* filename, @@ -55,11 +84,11 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, { if (strlen(filename) > 1000) { - fl_message("Unable to open file: "); + fprintf(stderr, "Unable to open file: "); } else { - fl_message("Unable to open file: %s", filename); + fprintf(stderr, "Unable to open file: %s", filename); } inStream.close(); return 0; @@ -70,9 +99,11 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, result->m_sequenceLength = 0; unsigned int maxSize = 1024; result->m_sequence = (BaseData*)malloc(sizeof(BaseData) * maxSize); + int numElements = 0; while (true) { - unsigned int junk; + numElements++; + unsigned int junk; // Check for a number. If not, ignore the line, or maybe the file is // done. @@ -134,13 +165,11 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, default: { if (strlen(filename) > 980) { - fl_message("Bad base: id %d, ", - result->m_sequenceLength + 1); + fprintf(stderr, "Bad base: id %d, ", result->m_sequenceLength + 1); } else { - fl_message("Bad base: id %d, file %s", - result->m_sequenceLength + 1, filename); + fprintf(stderr, "Bad base: id %d, file %s", result->m_sequenceLength + 1, filename); } delete result; inStream.close(); @@ -154,13 +183,12 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, { if (strlen(filename) > 980) { - fl_message("Bad prev id: id %d, ", - result->m_sequenceLength + 1); + fprintf(stderr, "Bad prev id: id %d, ", result->m_sequenceLength + 1); } else { - fl_message("Bad prev id: id %d, file %s", - result->m_sequenceLength + 1, filename); + fprintf(stderr, "Bad prev id: id %d, file %s", + result->m_sequenceLength + 1, filename); } delete result; inStream.close(); @@ -171,13 +199,13 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, { if (strlen(filename) > 980) { - fl_message("Bad next id: id %d, ", - result->m_sequenceLength + 1); + fprintf(stderr, "Bad next id: id %d, ", + result->m_sequenceLength + 1); } else { - fl_message("Bad next id: id %d, file %s", - result->m_sequenceLength + 1, filename); + fprintf(stderr, "Bad next id: id %d, file %s", + result->m_sequenceLength + 1, filename); } delete result; inStream.close(); @@ -189,19 +217,20 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, { if (strlen(filename) > 980) { - fl_message("Bad pair: id %d, ", + fprintf(stderr, "Bad pair: id %d, ", result->m_sequenceLength + 1); - } + } else { - fl_message("Bad pair: id %d, file %s", + fprintf(stderr, "Bad pair: id %d, file %s", result->m_sequenceLength + 1, filename); - } + } delete result; inStream.close(); return 0; } - if (result->m_sequence[result->m_sequenceLength].m_pair == 0) + result->m_sequence[result->m_sequenceLength].m_index = result->m_sequenceLength; + if (result->m_sequence[result->m_sequenceLength].m_pair == 0) { result->m_sequence[result->m_sequenceLength].m_pair = UNPAIRED; } @@ -216,13 +245,13 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, { if (strlen(filename) > 980) { - fl_message("Bad trailing id: id %d, ", - result->m_sequenceLength + 1); + fprintf(stderr, "Bad trailing id: id %d, ", + result->m_sequenceLength + 1); } else { - fl_message("Bad trailing id: id %d, file %s", - result->m_sequenceLength + 1, filename); + fprintf(stderr, "Bad trailing id: id %d, file %s", + result->m_sequenceLength + 1, filename); } delete result; inStream.close(); @@ -244,15 +273,17 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, if (result->m_sequenceLength == 0) { if (strlen(filename) > 990) - fl_message("Empty or malformed file: "); + fprintf(stderr, "Empty or malformed file: "); else - fl_message("Empty or malformed file: %s", filename); + fprintf(stderr, "Empty or malformed file: %s", filename); delete result; return 0; } result->m_sequence = (BaseData*)realloc(result->m_sequence, sizeof(BaseData)*result->m_sequenceLength); + + result->branchType = (RNABranchType_t*) malloc(sizeof(RNABranchType_t) * result->m_sequenceLength); result->m_pathname = strdup(filename); result->charSeqSize = tempSeq.size(); @@ -264,6 +295,7 @@ RNAStructure* RNAStructure::CreateFromFile(const char* filename, result->charSeq[i] = tempSeq.at(i); } + RNABranchType_t::PerformBranchClassification(result, result->m_sequenceLength); return result; } diff --git a/src/RNAStructure.h b/src/RNAStructure.h index 071b636..e0907a1 100755 --- a/src/RNAStructure.h +++ b/src/RNAStructure.h @@ -7,8 +7,18 @@ #include #include +#include + +#include #include +class RNABranchType_t; + +#define MAX(x, y) (x <= y ? y : x) +#define MIN(x, y) (x <= y ? x : y) +#define ABS(x) (x >= 0 ? x : -1 * x) +#define MIN3(x, y, z) MIN(x, MIN(y, z)) + class RNAStructure { public: @@ -31,15 +41,59 @@ class RNAStructure }; */ + class RNABranchType_t *branchType; + // A value for the pair of unpaired bases. static const unsigned int UNPAIRED; // Data on a single base - struct BaseData + class BaseData { - unsigned int m_pair; // The index of the base it is paired with, or UNPAIRED. + public: + unsigned int m_index; // The index of this structure + unsigned int m_pair; // The index of the base it is paired with, or UNPAIRED. Base m_base; // The base type. /*Truth m_truth; // How it compares to the reference structure */ + + inline char getBaseChar() const { + if(m_base == A) + return 'A'; + else if(m_base == C) + return 'C'; + else if(m_base == G) + return 'G'; + else if(m_base == U) + return 'U'; + else + return 'X'; + } + + /* + Determines whether this structure is logically contained within + a parent structure where containment is defined by enclosure of + arcs on the diagram circle. + @see RNABranchIdentification.h + */ + inline bool isContainedIn(const RNAStructure::BaseData &parentStruct) const { + unsigned int localIndexMin = MIN(m_index, m_pair); + unsigned int localIndexMax = MAX(m_index, m_pair); + unsigned int parentIndexMin = MIN(parentStruct.m_index, parentStruct.m_pair); + unsigned int parentIndexMax = MAX(parentStruct.m_index, parentStruct.m_pair); + if(parentStruct.m_pair == UNPAIRED) + return false; //return m_index >= parentIndexMin && m_index <= parentIndexMax; + else if(localIndexMax > parentIndexMax || localIndexMin < parentIndexMin) + return false; + else if(localIndexMin >= parentIndexMin && localIndexMax <= parentIndexMax) + return true; + return false; + } + /* + For use with the routines in BranchTypeIdentification.*: + */ + inline unsigned int getPairDistance() { + return ABS(MAX(m_pair, m_index) - MIN(m_pair, m_index)); + } + }; /* @@ -61,6 +115,12 @@ class RNAStructure Return the base at a given location. Indexed starting at 0. */ BaseData* GetBaseAt(unsigned int position); + RNABranchType_t* GetBranchTypeAt(unsigned int position); + //inline void SetBranchTypeAt(unsigned int position, class RNABranchType_t btValue) { + // if(position < m_sequenceLength) { + // *(branchType + position) = btValue; + // } + //} /* Return the number of bases in the sequence. @@ -97,12 +157,31 @@ class RNAStructure Display the contents of the file in a window (or bring it to the top if already existing). */ void DisplayFileContents(); + + /* + Returns a reference to the local m_sequence BaseData* pointer. + */ + inline BaseData* & getSequence() { + return m_sequence; + } + + inline void print() { + fprintf(stderr, "Printing RNAStructure of length = %u\n", GetLength()); + for(int i = 0; i < GetLength(); i++) { + BaseData *bdp = GetBaseAt(i); + fprintf(stderr, " => %u -> %u [%s]\n", bdp->m_index, bdp->m_pair, (bdp->m_pair == UNPAIRED) ? "UNPAIRED" : "PAIRED"); + } + } private: /* Constructor is private to force use of Create methods. */ RNAStructure(); + RNAStructure(const RNAStructure &rnaStruct); + RNAStructure & operator=(const RNAStructure &rhs); + + void copyRNAStructure(const RNAStructure &rnaStruct); /* Generate the string used for text display of the structure. @@ -125,8 +204,8 @@ class RNAStructure Fl_Double_Window* m_contentWindow; Fl_Text_Display* m_textDisplay; Fl_Text_Buffer* m_textBuffer; - char* m_displayString; + char* m_displayString; char* charSeq; unsigned int charSeqSize; }; diff --git a/src/StatsWindow.h b/src/StatsWindow.h index dfdadf4..29eb53d 100755 --- a/src/StatsWindow.h +++ b/src/StatsWindow.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include "RNAStructure.h" #include "StructureManager.h"