ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gfview/mdichild.cpp
Revision: 45
Committed: Tue Sep 6 18:19:20 2011 UTC (10 years, 8 months ago) by gpertea
File size: 24028 byte(s)
Log Message:
added gfview files

Line User Rev File contents
1 gpertea 45 /********************************************************************************
2     * *
3     * *
4     *********************************************************************************/
5    
6     #include <stdio.h>
7     #include "mdichild.h"
8     #include "clv_icons.h"
9    
10     /*******************************************************************************/
11    
12    
13     // ========= static members initialization: ================
14     short MDIChild::numInst=0; //number of instances
15     FXFont* MDIChild::ifont=NULL;
16     FXIcon* MDIChild::icnDefCS=NULL;
17     FXIcon* MDIChild::icnBaseCS=NULL;
18     FXIcon* MDIChild::icnDensCS=NULL;
19     //============================================================
20    
21     // Map
22     FXDEFMAP(MDIChild) MDIChildMap[]={
23     //________Message_Type____________________ID___________________Message_Handler________
24     FXMAPFUNCS(SEL_CHANGED, MDIChild::ID_CLXZOOM,
25     MDIChild::ID_CLYZOOM, MDIChild::onCmdClZoom),
26     FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CLNOZOOM, MDIChild::onNoZoom),
27     FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CLGRPS, MDIChild::onCmdGrps),
28     FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CL1PXZOOM, MDIChild::onMaxZoom),
29     FXMAPFUNC(SEL_CLICKED, MDIChild::ID_CLVIEW, MDIChild::onSeqSelect),
30     FXMAPFUNC(SEL_RIGHTBUTTONPRESS, MDIChild::ID_CLVIEW, MDIChild::onRMouseDown),
31     FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, MDIChild::ID_CLVIEW, MDIChild::onRMouseUp),
32     FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, MDIChild::ID_CLVIEW, MDIChild::onMMouseDown),
33     FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, MDIChild::ID_CLVIEW, MDIChild::onMMouseUp),
34     FXMAPFUNC(SEL_MOTION, MDIChild::ID_CLVIEW, MDIChild::onMouseMove),
35     FXMAPFUNCS(SEL_COMMAND, MDIChild::ID_CSTYLE1,
36     MDIChild::ID_CSTYLE3, MDIChild::onColorOption),
37     FXMAPFUNC(SEL_COMMAND, MDIChild::ID_CONTIG, MDIChild::onSelContig),
38     FXMAPFUNC(SEL_COMMAND, MDIChild::ID_HIDEGAPS, MDIChild::onHideGaps),
39     FXMAPFUNC(SEL_COMMAND, MDIChild::ID_SELSEQ, MDIChild::onSelSeq),
40     FXMAPFUNC(SEL_CONFIGURE, 0, MDIChild::onMaxRestore),
41     };
42    
43    
44     // Object implementation
45     FXIMPLEMENT(MDIChild,FXMDIChild,MDIChildMap,ARRAYNUMBER(MDIChildMap))
46    
47    
48     /*******************************************************************************/
49     // Make some windows
50     MDIChild::MDIChild(FXMDIClient* p,const FXString& name,FXIcon* ic,
51     FXMenuPane* mn,FXuint opts,FXint x,FXint y,FXint w,FXint h)
52     :FXMDIChild(p,name, ic, mn, opts, x, y, w, h) {
53     FXString s;
54     // Tooltip
55     wasMaximized=false;
56     new FXToolTip(getApp());
57     layoutparser=NULL;
58     groupHolder=NULL;
59     zooming=false;
60     panning=false;
61     prevColumn=-1;
62     contents=new FXVerticalFrame(this,FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0);
63    
64     vframe=new FXVerticalFrame(contents,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_FILL_X,
65     0,0,0,0,0,0,0,0);
66     FXHorizontalFrame* hf=new FXHorizontalFrame(vframe,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP);
67     //contig and option buttons:
68     new FXLabel(hf, "Cluster:", NULL, LAYOUT_CENTER_Y);
69    
70     selcontig=new FXComboBox(hf,32,this,ID_CONTIG,
71     COMBOBOX_NORMAL|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y);
72     selcontig->setNumVisible(10);
73     selcontig->setEditable(FALSE);
74     pop=new FXPopup(this);
75     if (numInst<=0) {
76     icnDefCS=new FXXPMIcon(getApp(), cs_default, FXRGB(192,192,192),IMAGE_ALPHACOLOR);
77     icnBaseCS=new FXXPMIcon(getApp(), cs_base, FXRGB(192,192,192),IMAGE_ALPHACOLOR);
78     icnDensCS=new FXXPMIcon(getApp(), cs_density, FXRGB(192,192,192),IMAGE_ALPHACOLOR);
79     ifont=new FXFont(getApp(),"helvetica", 10, FXFont::Bold); //info font
80     }
81     numInst++;
82    
83     clropt1=new FXOption(pop,"\t\tCoverage/quality color style",
84     icnDensCS,
85     this,ID_CSTYLE2,JUSTIFY_HZ_APART);
86     clropt2=new FXOption(pop,"\t\tSimple/Group color style", icnDefCS,
87     this, ID_CSTYLE1,JUSTIFY_HZ_APART);
88     clropt3=new FXOption(pop,"\t\tNucleotide color style",
89     icnBaseCS,
90     this,ID_CSTYLE3,JUSTIFY_HZ_APART);
91     new FXOptionMenu(hf, pop,
92     LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|JUSTIFY_HZ_APART);
93     new FXButton(hf, "G\tLoad groups\tShow groups loaded from another layout file",
94     NULL,this, ID_CLGRPS,
95     LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|JUSTIFY_HZ_APART);
96     cbgaps=new FXCheckButton(hf,"hide contig gaps",this, MDIChild::ID_HIDEGAPS);
97     hframe=new FXHorizontalFrame(vframe,FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_Y|ICON_BEFORE_TEXT,
98     0,0,0,0,0,0,0,0);
99     vframe= new FXVerticalFrame(hframe,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_FILL_X,
100     0,0,0,0,0,0,0,0);
101     clframe=new FXHorizontalFrame(vframe,FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_BOTTOM,
102     0,0,0,0,0,0,0,0);
103     alignview=new FXGView(clframe, this,MDIChild::ID_CLVIEW, LAYOUT_FILL_X|LAYOUT_FILL_Y);
104    
105     hf = new FXHorizontalFrame(vframe,FRAME_SUNKEN|LAYOUT_FILL_X,
106     0,0,0,0,0,0,0,0);
107     //=== seq_info box:
108     FXVerticalFrame* vf = new FXVerticalFrame(hf, FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FILL_X);
109     FXHorizontalFrame* hhf=new FXHorizontalFrame(vf,
110     FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FILL_X, 0,0,0,0,0,0,0,0);
111     selseq=new FXComboBox(hhf,28,this,ID_SELSEQ,
112     COMBOBOX_NORMAL|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y);
113     selseq->setNumVisible(12);
114     selseq->setEditable(FALSE);
115     seqData = new FXLabel(hhf, " ", NULL,
116     FRAME_SUNKEN|JUSTIFY_LEFT|LAYOUT_FILL_X);
117     //seqComment=new FXTextField(vf,120,NULL,0,JUSTIFY_LEFT|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X);
118     seqData->setFont(ifont);
119     seqAsmInfo=new FXLabel(vf, " ", NULL,
120     FRAME_SUNKEN|JUSTIFY_LEFT|LAYOUT_FILL_X);
121     seqAsmInfo->setFont(ifont);
122     //===slider box:
123     vf = new FXVerticalFrame(hf, FRAME_RAISED);
124     sliderZX=new FXSlider(vf,this,MDIChild::ID_CLXZOOM,
125     LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|FRAME_RAISED,
126     0,0,160,22,0,0,0,0);
127    
128     hf=new FXHorizontalFrame(vf,FRAME_NONE|LAYOUT_FILL_X,0,0,0,0,0,0,0,0);
129     nozoomBtn=new FXButton(hf, "&1x1",NULL, this, MDIChild::ID_CLNOZOOM,
130     FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y);
131     new FXButton(hf, "1p&x",NULL, this, MDIChild::ID_CL1PXZOOM,
132     FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_X|LAYOUT_CENTER_Y);
133     zxLabel=new FXLabel(hf, "1.000", NULL,
134     FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,
135     0,0,6*6,14);
136    
137     s.format("%02.3f",alignview->getZoomX());
138     zxLabel->setText(s);
139     columnInfo=new FXLabel(vframe, " ",
140     NULL, JUSTIFY_LEFT|FRAME_SUNKEN|LAYOUT_FILL_X);
141     //=== vframe filled ===
142    
143     toolframe=new FXVerticalFrame(hframe,FRAME_RAISED|LAYOUT_FILL_Y);
144     //new FXLabel(toolframe, "Y Scale:", NULL, LAYOUT_CENTER_X);
145     sliderZY=new FXSlider(toolframe,this,MDIChild::ID_CLYZOOM,
146     SLIDER_VERTICAL|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_CENTER_X|FRAME_RAISED,
147     0,0,22,140,0,0,0,0);
148    
149     sliderZY->setRange(10,100); //
150     sliderZY->setValue((FXint)(alignview->getZoomY()*100));
151    
152     sliderZX->setRange(10,1000);//
153     sliderZX->setValue((FXint)(alignview->getZoomX()*1000));
154     s.format("%02.2f",alignview->getZoomY());
155     zyLabel=new FXLabel(toolframe, s, NULL,
156     FRAME_SUNKEN|LAYOUT_CENTER_X|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,
157     0,0,6*6,14);
158    
159     alignview->setFocus();
160     }
161    
162     void MDIChild::showSeqInfo(ClSeq* seq) {
163     FXString s;
164    
165     if (seq!=NULL && seq==alignview->selSeq) { //selection
166     s.format("%s (%d nt)", seq->name.text(), seq->len);
167     selseq->setText(s);
168     if (seq->ins>0 || seq->dels>0)
169     s.format(" %s range: %d to %d | clipL:%d clipR:%d | gaps: %d dels: %d",
170     seq->reversed?"-":"+",
171     seq->clipL+1, seq->len-seq->clipR,
172     seq->clipL, seq->clipR,
173     seq->ins, seq->dels);
174    
175     else
176     s.format(" %s range: %d to %d | clipL:%d clipR:%d ",
177     seq->reversed?"-":"+",
178     seq->clipL+1, seq->len-seq->clipR,
179     seq->clipL, seq->clipR);
180     seqData->setText(s);
181     //seqComment->setText(seq->comment);
182     if (seq->group>=0)
183     s.format("Layout location: %d to %d [group %d]",
184     seq->cl_xpos+seq->clipL, seq->cl_xpos+seq->len-seq->clipR-1, seq->group);
185     else
186     s.format("Layout location: %d to %d",
187     seq->cl_xpos+seq->clipL, seq->cl_xpos+seq->len-seq->clipR-1);
188     seqAsmInfo->setText(s);
189     }
190     else { //deselect
191     selseq->setText(" ");
192     seqData->setText(" ");
193     seqAsmInfo->setText(" ");
194     }
195     int cidx=alignview->getSelCol();
196     if (prevColumn==cidx) return;
197     prevColumn=cidx;
198     FXString cinfo;
199     if (cidx>=0) {
200     ColumnData* c=alignview->getColumnData(cidx);
201     if (c->letter!=0) {
202     cinfo.format("Column %d ['%c']: %d layers, %d mismatches ",
203     cidx+alignview->getXLeft(), c->letter, c->thickness, c->mismatches);
204     if (c->mismatches>1 && c->thickness>3) {
205     cinfo+=" [ ";
206     for (int i=0;i<3;i++) {
207     if (c->ntdata[i].count>0) {
208     s.format(" %d%c ", c->ntdata[i].count, c->ntdata[i].letter);
209     cinfo+=s;
210     }
211     }
212     cinfo+=" ] ";
213     }
214     }
215     else
216     cinfo.format("Column %d (%d layers)", cidx+alignview->getXLeft(), c->thickness);
217     columnInfo->setText(cinfo);
218     }
219     else {
220     columnInfo->setText(" ");
221     }
222     }
223    
224     long MDIChild::onSeqSelect(FXObject*,FXSelector sel,void* ptr){
225     showSeqInfo((ClSeq*)ptr);
226     return 1;
227     }
228    
229     long MDIChild::onCmdClZoom(FXObject*,FXSelector sel,void*){
230     FXuint sid=FXSELID(sel);
231     FXString s;
232     switch(sid) {
233     case ID_CLXZOOM:
234     alignview->ZoomX(((double)sliderZX->getValue())/1000);
235     s.format("%2.3f",alignview->getZoomX());
236     zxLabel->setText(s);
237     break;
238     case ID_CLYZOOM:
239     alignview->ZoomY(((double)sliderZY->getValue())/100);
240     s.format("%2.2f",alignview->getZoomY());
241     zyLabel->setText(s);
242     break;
243     }
244     return 1;
245     }
246    
247     long MDIChild::onColorOption(FXObject*,FXSelector sel,void*){
248     FXuint sid=FXSELID(sel);
249     switch(sid) {
250     case ID_CSTYLE1:
251     alignview->setColorStyle(FXGView::csDefault);
252     break;
253     case ID_CSTYLE2:
254     alignview->setColorStyle(FXGView::csDensity);
255     break;
256     case ID_CSTYLE3:
257     alignview->setColorStyle(FXGView::csBaseColor);
258     break;
259     }
260     this->ungrab(); //? bug?
261     return 1;
262     }
263    
264     // Show up
265     void MDIChild::create(){
266     FXMDIChild::create();
267     show();
268     }
269    
270    
271     long MDIChild::onRMouseDown(FXObject*,FXSelector,void* ptr) {
272     FXEvent *ev = (FXEvent*)ptr;
273     //prevCursor=getApp();
274     alignview->setDragCursor(getApp()->getDefaultCursor(DEF_MOVE_CURSOR));
275     alignview->grab();
276     // While the right-button mouse is down, do zooming
277     zooming=true;
278     startZX=alignview->getZoomX();
279     startZY=alignview->getZoomY();
280     zoomPt.x=ev->win_x;
281     zoomPt.y=ev->win_y;
282     return 1;
283     }
284    
285     long MDIChild::onMMouseDown(FXObject*,FXSelector,void* ptr) {
286     //FXEvent *ev = (FXEvent*)ptr;
287     //prevCursor=getApp();
288     alignview->setDragCursor(getApp()->getDefaultCursor(DEF_MOVE_CURSOR));
289     alignview->grab();
290     // While the right-button mouse is down, do zooming
291     panning=true;
292     //startZX=alignview->getZoomX();
293     //startZY=alignview->getZoomY();
294     //zoomPt.x=ev->win_x;
295     //zoomPt.y=ev->win_y;
296     return 1;
297     }
298    
299     long MDIChild::onMouseMove(FXObject*, FXSelector, void* ptr){
300     FXEvent *ev=(FXEvent*)ptr;
301     if (zooming) {
302     //compute distance:
303     //int dx=(ev->win_x-zoomPt.x)*2;
304     //int dy=(zoomPt.y-ev->win_y)/3;
305     double newzx = startZX+((double)(ev->win_x-zoomPt.x)*2)/1000;
306     double newzy = startZY+(((double)(zoomPt.y-ev->win_y))/3)/100;
307     int minzx, maxzx;
308     int minzy, maxzy;
309     sliderZX->getRange(minzx, maxzx);
310     sliderZY->getRange(minzy, maxzy);
311     if (newzx*1000<minzx) newzx=(double)minzx/1000;
312     else
313     if (newzx*1000>maxzx) newzx=(double)maxzx/1000;
314     if (newzy*100<minzy) newzy=(double)minzy/100;
315     else
316     if (newzy*100>maxzy) newzy=(double)maxzy/100;
317     if (newzx!=alignview->getZoomX() ||
318     newzy!=alignview->getZoomY()) {
319     alignview->Zoom(newzx,newzy,
320     zoomPt.x, zoomPt.y);
321     FXString s;
322     sliderZX->setValue((FXint)(newzx*1000));
323     sliderZX->forceRefresh();
324     s.format("%2.3f",alignview->getZoomX());
325     zxLabel->setText(s);
326     sliderZY->setValue((FXint)(newzy*100));
327     sliderZY->forceRefresh();
328     s.format("%2.2f",alignview->getZoomY());
329     zyLabel->setText(s);
330     }
331     }
332     if (panning) {
333     alignview->scrollBy((ev->win_x-ev->last_x)*2, (ev->win_y-ev->last_y)*2);
334     }
335     return 1;
336     }
337    
338    
339     long MDIChild::onNoZoom(FXObject*,FXSelector sel,void*) {
340     sliderZX->setValue(1000);
341     zxLabel->setText("1.000");
342     sliderZY->setValue(100);
343     zyLabel->setText("1.00");
344     alignview->Zoom(1,1);
345     return 1;
346     }
347    
348     long MDIChild::onMaxZoom(FXObject*,FXSelector sel,void*) {
349     FXString s;
350     double newzx, newzy;
351     alignview->set1pxZoom();
352     newzx=alignview->getZoomX();
353     newzy=alignview->getZoomY();
354     sliderZX->setValue((FXint)(newzx*1000));
355     sliderZX->forceRefresh();
356     s.format("%2.3f",newzx);
357     zxLabel->setText(s);
358     sliderZY->setValue((FXint)(newzy*100));
359     sliderZY->forceRefresh();
360     s.format("%2.2f",newzy);
361     zyLabel->setText(s);
362     return 1;
363     }
364    
365     long MDIChild::onCmdGrps(FXObject*,FXSelector sel,void*) {
366     FXString ofile=FXFileDialog::getOpenFilename(this,"Open file", //NULL,
367     "Contig files (*.ace,*.lyt)\nAny file (*)");
368     if (!ofile.empty()) loadGroups(ofile);
369     return 1;
370     }
371    
372    
373    
374     long MDIChild::onRMouseUp(FXObject*,FXSelector,void* ptr){
375     //FXEvent *ev=(FXEvent*) ptr;
376     alignview->ungrab();
377     zooming=false;
378     if (!panning)
379     alignview->setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
380     return 1;
381     }
382    
383     long MDIChild::onMMouseUp(FXObject*,FXSelector,void* ptr){
384     alignview->ungrab();
385     panning=false;
386     if (!zooming)
387     alignview->setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
388     return 1;
389     }
390    
391    
392     bool MDIChild::openFile(const char* filename) {
393     //try to recognize the file type and call the appropriate loader
394     FILE* f;
395     if ((f=fopen(filename, "r"))==NULL) {
396     FXMessageBox::error(this,MBOX_OK,"File error",
397     "Cannot open file '%s'", filename);
398     }
399     fclose(f);
400     FXString fname(filename);
401     AceParser ap(fname.text());
402     if (ap.open()) {
403     delete layoutparser;
404     layoutparser=NULL;
405     layoutparser=new AceParser(fname.text());
406     return loadLayoutFile(fname);
407     }
408     else { //assumes it's our layout format file
409     delete layoutparser;
410     layoutparser=NULL;
411     layoutparser=new LayoutParser(fname.text());
412     }
413     return loadLayoutFile(fname);
414     }
415    
416    
417     bool MDIChild::loadLayoutFile(FXString& lytfile) {
418     if (!layoutparser->open()) {
419     FXMessageBox::error(this,MBOX_OK,"File error",
420     "Cannot open file '%s'. Not a valid file?", lytfile.text());
421     delete layoutparser;
422     layoutparser=NULL;
423     return false;
424     }
425     alignview->filetype=layoutparser->getFileType();
426     isAce=(alignview->filetype=='A');
427     if (!layoutparser->parseContigs() || layoutparser->getNumContigs()==0) {
428     //if (!layoutparser->parse() || layoutparser->getNumContigs()==0) {
429     FXMessageBox::error(this,MBOX_OK,"File error",
430     "Error encountered parsing file '%s'. Not a valid file?", lytfile.text());
431     delete layoutparser;
432     layoutparser=NULL;
433     return false;
434     }
435     file=lytfile;
436     //file validated. Load align data:
437     //show all contig labels:
438     layoutparser->contigsByNumSeqs();
439     FXString name;
440     for (int i=0; i<layoutparser->getNumContigs(); i++) {
441     LytCtgData* ctg=layoutparser->getContig(i);
442     name.format("%s (%d seqs, %d nts)", ctg->name, ctg->numseqs,
443     ctg->len);
444     selcontig->appendItem(name);
445     }
446     //show first contig:
447     selcontig->setCurrentItem(0);
448     selContig(0, cbgaps->getCheck());
449     if (alignview->HasSeqs()) {
450     clropt3->enable();
451     cbgaps->show();
452     }
453     else {
454     clropt3->disable();
455     cbgaps->hide();
456     }
457     alignview->setColorStyle(FXGView::csDensity);
458     return true;
459     }
460    
461     void MDIChild::loadGroups(FXString& lytfile) {
462     //assumes sequences already loaded here
463     if (alignview->seqlist->Count()==0) {
464     FXMessageBox::error(this,MBOX_OK,"Action error",
465     "You need a valid layout file loaded before setting groups.");
466     return;
467     }
468     LayoutParser* lp = new AceParser(lytfile.text());
469     if (!lp->open()) { //try ACE first
470     delete lp;
471     lp=new LayoutParser(lytfile.text());
472     }
473     else lp->close();
474     if (!lp->open() ||
475     !lp->parse()) {
476     FXMessageBox::error(this,MBOX_OK,"File error",
477     "Error encountered opening/parsing layout file '%s'. Not a layout file?", lytfile.text());
478     delete lp;
479     return;
480     }
481     delete groupHolder;
482     //groupHolder=NULL;
483     groupHolder=lp;
484     assignGroups();
485     }
486    
487     void MDIChild::assignGroups() {
488     if (groupHolder==NULL) return;
489     int numGroups=0;
490     //we must count only contigs having at least one
491     //sequence in common with the currently displayed layout
492     //for each contig, test all component sequences
493     //groupHolder->parseContigs();
494     int nc=groupHolder->getNumContigs();
495     for (int i=0; i<nc; i++) {
496     LytCtgData* ctg=groupHolder->getContig(i);
497     bool assigned=false;
498     //for each sequence, see if it's in the viewer's current layout
499     for (int j=0;j<ctg->numseqs;j++) {
500     FXString s(ctg->seqs[j]->name);
501     if (alignview->setSeqGrp(s, numGroups)) assigned=true;
502     }
503     if (assigned) numGroups++; //advance to next group
504     }
505     if (numGroups>0) {
506     //alignview->initGrpColors(numGroups);
507     alignview->update();
508     }
509     else
510     FXMessageBox::information(this,MBOX_OK,"Information",
511     "No groups were found for sequences in the selected contig");
512     }
513    
514     void MDIChild::selContig(int ctgno, bool hideGaps) {
515     if (ctgno<0 || ctgno>=layoutparser->getNumContigs()) return;
516     alignview->Clear();
517     FXApp* fapp=getApp();
518     fapp->beginWaitCursor();
519     fapp->forceRefresh();
520    
521     layoutparser->loadContig(ctgno);
522     LytCtgData* ctg=layoutparser->getContig(ctgno);
523     char *ctgseq=layoutparser->getContigSeq(ctg);
524     //now ctgseq contains '*'
525     //for each position, record how many '*' chars we have on the left
526     int* ctgrm=NULL;
527     bool removeGaps=hideGaps;
528     int ctglen=ctg->len;
529     if (removeGaps && ctgseq!=NULL) {
530     int len=strlen(ctgseq);
531     GMALLOC(ctgrm, (len+1)*sizeof(int));
532     int numstars=0;
533     ctgrm[0]=0;
534     for (int i=1;i<len;i++) {
535     numstars += (ctgseq[i-1]=='*');
536     ctgrm[i]=numstars;
537     }
538     ctgrm[len]=ctgrm[len-1];
539     //now remove all the stars from the contig sequence
540     if (numstars>0) {
541     char* cleanseq=NULL;
542     GMALLOC(cleanseq, len-numstars+1);
543     ctglen-=numstars;
544     int j=0;
545     for (int i=0;i<=len;i++)
546     if (ctgseq[i]!='*') {
547     cleanseq[j] = ctgseq[i];
548     j++;
549     }
550     GFREE(ctgseq);
551     ctgseq=cleanseq;
552     removeGaps=true;
553     }
554     else removeGaps=false;
555     }
556     alignview->addContig(ctg->name, ctglen, ctgseq, ctg->offs);
557     GFREE(ctgseq);
558     int numseqs=ctg->numseqs;
559     for (int i=0;i<numseqs;i++) { //reload each read sequence
560     LytSeqInfo* seq=ctg->seqs[i];
561    
562     char* s=layoutparser->getSeq(seq);
563     // GMessage("seq %d : %s \n", i, seq->name);
564    
565     int slen=0;
566     if (isAceFile() && (s==NULL || (slen=strlen(s))!=(unsigned int)seq->seglen())) {
567     FXMessageBox::error(this,MBOX_OK,"File error",
568     "Error reading sequence '%s' (declared %d, loaded %d). Invalid ACE file?",
569     seq->name, seq->length(), slen);
570     delete layoutparser;
571     layoutparser=NULL;
572     GFREE(s);
573     return;
574     }
575     if (removeGaps && s!=NULL) {
576     //shift all coordinates and lengths accordingly, remove gaps
577     int clpL=seq->left-1;
578     int clpR=seq->length()-seq->right;
579     int old_start=seq->offs+clpL;
580     int old_end=seq->offs+seq->length()-clpR-1;
581     int new_start=old_start-ctgrm[old_start-1];
582     int new_end=old_end-ctgrm[old_end-1];
583     //fix interseg coordinates too, when introns are given
584     // otherwise the "remove gaps" is going to mess up the MSA !!
585    
586     for (int g = 0; g < seq->numisegs; g++) {
587     int prevcoord=seq->intersegs[g].segEnd;
588     seq->intersegs[g].segEnd-=ctgrm[prevcoord-1];
589     prevcoord=seq->intersegs[g].nextStart;
590     seq->intersegs[g].nextStart-=ctgrm[prevcoord-1];
591     }
592     //now create the cleaned copy of the sequence
593     char* clnseq=NULL;
594     int newlen=new_end-new_start+1+clpL+clpR;
595     GMALLOC(clnseq, sizeof(char)*(newlen+1));
596     clnseq[newlen]='\0';
597     if (clpL>0) strncpy(clnseq, s, clpL);
598     int j=clpL;
599     int numdels=0;
600     int numins=0;
601     for (int b=clpL; b<seq->length()-clpR; b++) {
602     int ctgpos=seq->offs+b;
603     //delete only if there was also a '*' in the initial contig seq
604     if (ctgrm[ctgpos]-ctgrm[ctgpos-1]==0) {
605     clnseq[j] = s[b];
606     if (s[b]=='*' || s[b]=='-') {
607     clnseq[j]='-';
608     numins++;
609     }
610     j++;
611     }
612     else {
613     if (s[b]!='*' && s[b]!='-')
614     numdels++;
615     }
616     }
617     clnseq[j]='\0';
618     if (clpR>0) strncat(clnseq, s+(seq->length()-clpR), clpR);
619     GFREE(s);
620     s=clnseq;
621     alignview->addSeq(seq->name, newlen, new_start-clpL, seq->reversed,
622     clpL,clpR,s, numins, numdels);
623     //alignview->addSeq(seq,s);
624     } //gaps removal
625     else { // raw sequence display (with all gaps in place)
626     /*alignview->addSeq(seq->name, seq->length(), seq->offs, seq->reversed,
627     seq->left-1,seq->length()-seq->right,s);*/
628     alignview->addSeq(seq,s);
629     }
630     GFREE(s);
631     }
632     alignview->buildLayout();
633     assignGroups();
634     selseq->clearItems();
635     showSeqInfo(NULL);
636     for (int i=0;i<alignview->seqlist->Count();i++) {
637     ClSeq* seq=alignview->seqlist->Get(i);
638     if (seq==alignview->contig) continue;
639     FXString name;
640     name.format ("%s (%d nt)", seq->name.text(), seq->len);
641     selseq->appendItem(name);
642     }
643     fapp->endWaitCursor();
644     if (alignview->HasSeqs()) {
645     clropt3->enable();
646     cbgaps->show();
647     }
648     else {
649     clropt3->disable();
650     cbgaps->hide();
651     }
652     }
653    
654     long MDIChild::onSelContig(FXObject*,FXSelector,void* ptr) {
655     selContig(selcontig->getCurrentItem(), cbgaps->getCheck());
656     return 1;
657     }
658    
659     long MDIChild::onHideGaps(FXObject*,FXSelector,void* ptr) {
660     selContig(selcontig->getCurrentItem(), cbgaps->getCheck());
661     return 1;
662     }
663    
664    
665     long MDIChild::onSelSeq(FXObject*,FXSelector,void* ptr) {
666     int seqidx=selseq->getCurrentItem();
667     if (seqidx<0) return 1;
668     ClSeq* seq=alignview->seqlist->Get(seqidx);
669     alignview->selectSeq(seq, true);
670     showSeqInfo(seq);
671     return 1;
672     }
673    
674     long MDIChild::onMaxRestore(FXObject* sender,FXSelector sel,void* ptr) {
675     FXbool maximized=isMaximized();
676     if (wasMaximized!=maximized) {
677     FXWindow* mainwin=getShell();
678     mainwin->handle(mainwin, FXSEL(SEL_COMMAND, ID_MAXRESTORE),ptr);
679     wasMaximized=maximized;
680     }
681     return FXMDIChild::handle(sender,sel,ptr);
682     }
683    
684     MDIChild::~MDIChild() {
685     delete pop;
686     delete layoutparser;
687     delete groupHolder;
688     //== static members:
689     numInst--;
690     if (numInst==0) {
691     delete ifont;
692     delete icnDefCS;
693     delete icnBaseCS;
694     delete icnDensCS;
695     }
696     }