void ViewPort::SetBoxes( void ) { // In the case where canvas rotation is applied, we need to define a larger "virtual" pixel window size to ensure that // enough chart data is fatched and available to fill the rotated screen. rv_rect = wxRect( 0, 0, pix_width, pix_height ); // Specify the minimum required rectangle in unrotated screen space which will supply full screen data after specified rotation if( ( g_bskew_comp && ( fabs( skew ) > .001 ) ) || ( fabs( rotation ) > .001 ) ) { double rotator = rotation; if(g_bskew_comp) rotator -= skew; int dy = wxRound( fabs( pix_height * cos( rotator ) ) + fabs( pix_width * sin( rotator ) ) ); int dx = wxRound( fabs( pix_width * cos( rotator ) ) + fabs( pix_height * sin( rotator ) ) ); // It is important for MSW build that viewport pixel dimensions be multiples of 4..... if( dy % 4 ) dy += 4 - ( dy % 4 ); if( dx % 4 ) dx += 4 - ( dx % 4 ); int inflate_x = wxMax(( dx - pix_width ) / 2, 0); int inflate_y = wxMax(( dy - pix_height ) / 2, 0); // Grow the source rectangle appropriately if( fabs( rotator ) > .001 ) rv_rect.Inflate( inflate_x, inflate_y ); } // Compute Viewport lat/lon reference points for co-ordinate hit testing // This must be done in unrotated space with respect to full unrotated screen space calculated above double rotation_save = rotation; SetRotationAngle( 0. ); wxPoint ul( rv_rect.x, rv_rect.y ), lr( rv_rect.x + rv_rect.width, rv_rect.y + rv_rect.height ); double dlat_min, dlat_max, dlon_min, dlon_max; bool hourglass = false; switch(m_projection_type) { case PROJECTION_TRANSVERSE_MERCATOR: case PROJECTION_STEREOGRAPHIC: case PROJECTION_GNOMONIC: hourglass = true; case PROJECTION_POLYCONIC: case PROJECTION_POLAR: case PROJECTION_ORTHOGRAPHIC: { double d; if( clat > 0 ) { // north polar wxPoint u( rv_rect.x + rv_rect.width/2, rv_rect.y ); wxPoint ur( rv_rect.x + rv_rect.width, rv_rect.y ); GetLLFromPix( ul, &d, &dlon_min ); GetLLFromPix( ur, &d, &dlon_max ); GetLLFromPix( lr, &dlat_min, &d ); GetLLFromPix( u, &dlat_max, &d ); if(fabs(fabs(d - clon) - 180) < 1) { // the pole is onscreen dlat_max = 90; dlon_min = -180; dlon_max = 180; } else if(wxIsNaN(dlat_max)) dlat_max = 90; if(hourglass) { // near equator, center may be less wxPoint l( rv_rect.x + rv_rect.width/2, rv_rect.y + rv_rect.height ); double dlat_min2; GetLLFromPix( l, &dlat_min2, &d ); dlat_min = wxMin(dlat_min, dlat_min2); } if(wxIsNaN(dlat_min)) // world is off-screen dlat_min = clat - 90; } else { // south polar wxPoint l( rv_rect.x + rv_rect.width/2, rv_rect.y + rv_rect.height ); wxPoint ll( rv_rect.x, rv_rect.y + rv_rect.height ); GetLLFromPix( ul, &dlat_max, &d ); GetLLFromPix( lr, &d, &dlon_max ); GetLLFromPix( ll, &d, &dlon_min ); GetLLFromPix( l, &dlat_min, &d ); if(fabs(fabs(d - clon) - 180) < 1) { // the pole is onscreen dlat_min = -90; dlon_min = -180; dlon_max = 180; } else if(wxIsNaN(dlat_min)) dlat_min = -90; if(hourglass) { // near equator, center may be less wxPoint u( rv_rect.x + rv_rect.width/2, rv_rect.y ); double dlat_max2; GetLLFromPix( u, &dlat_max2, &d ); dlat_max = wxMax(dlat_max, dlat_max2); } if(wxIsNaN(dlat_max)) // world is off-screen dlat_max = clat + 90; } if(wxIsNaN(dlon_min)) { // if neither pole is visible, but left and right of the screen are in space // we can avoid drawing the far side of the earth if(dlat_max < 90 && dlat_min > -90) { dlon_min = clon - 90 - fabs(clat); // this logic is not optimal, is it always correct? dlon_max = clon + 90 + fabs(clat); } else { dlon_min = -180; dlon_max = 180; } } } break; default: // works for mercator and equirectangular { GetLLFromPix( ul, &dlat_max, &dlon_min ); GetLLFromPix( lr, &dlat_min, &dlon_max ); } } if( clon < dlon_min ) dlon_min -= 360; else if(clon > dlon_max) dlon_max += 360; // Set the viewport lat/lon bounding box appropriately vpBBox.SetMin( dlon_min, dlat_min ); vpBBox.SetMax( dlon_max, dlat_max ); // Restore the rotation angle SetRotationAngle( rotation_save ); }
VampEffectDialog::VampEffectDialog(VampEffect *effect, wxWindow *parent, Vamp::Plugin *plugin) : wxDialog(parent, -1, effect->GetEffectName(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), mEffect(effect), mPlugin(plugin) { Vamp::Plugin::ProgramList programs = plugin->getPrograms(); mParameters = plugin->getParameterDescriptors(); #ifdef __WXMSW__ // On Windows, for some reason, wxWindows calls OnTextCtrl during creation // of the text control, and VampEffectDialog::OnTextCtrl calls HandleText, // which assumes all the fields have been initialized. // This can give us a bad pointer crash, so manipulate inSlider to // no-op HandleText during creation. inSlider = true; #else inSlider = false; #endif inText = false; int count = mParameters.size(); toggles = new wxCheckBox*[count]; sliders = new wxSlider*[count]; fields = new wxTextCtrl*[count]; labels = new wxStaticText*[count]; combos = new wxComboBox*[count]; wxControl *item; wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL); item = new wxStaticText(this, 0, LAT1CTOWX(plugin->getName().c_str()) + wxString(_(" - Vamp audio analysis plugin"))); vSizer->Add(item, 0, wxALL, 5); item = new wxStaticText(this, 0, LAT1CTOWX(plugin->getDescription().c_str())); vSizer->Add(item, 0, wxALL, 5); item = new wxStaticText(this, 0, wxString(_("Author: ")) + LAT1CTOWX(plugin->getMaker().c_str())); vSizer->Add(item, 0, wxALL, 5); item = new wxStaticText(this, 0, LAT1CTOWX(plugin->getCopyright().c_str())); vSizer->Add(item, 0, wxALL, 5); wxScrolledWindow *w = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxTAB_TRAVERSAL); // Try to give the window a sensible default/minimum size w->SetMinSize(wxSize( wxMax(400, parent->GetSize().GetWidth() / 2), parent->GetSize().GetHeight() / 2)); w->SetScrollRate(0, 20); vSizer->Add(w, 1, wxEXPAND|wxALL, 5); vSizer->Add(CreateStdButtonSizer(this, eCancelButton|eOkButton), 0, wxEXPAND); SetSizer(vSizer); wxSizer *paramSizer = new wxStaticBoxSizer(wxVERTICAL, w, _("Plugin Settings")); wxFlexGridSizer *gridSizer = new wxFlexGridSizer(5, 0, 0); gridSizer->AddGrowableCol(3); programCombo = 0; if (!programs.empty()) { wxArrayString choices; wxString currentProgram = wxString(mPlugin->getCurrentProgram().c_str(), wxConvISO8859_1); for (size_t i = 0; i < programs.size(); ++i) { wxString choice = wxString(programs[i].c_str(), wxConvISO8859_1); choices.Add(choice); } gridSizer->Add(new wxStaticText(w, 0, _("Program")), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); programCombo = new wxComboBox(w, 9999, currentProgram, wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY); programCombo->SetName(_("Program")); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(programCombo, 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5); ConnectFocus(programCombo); gridSizer->Add(1, 1, 0); } for (int p = 0; p < count; p++) { wxString labelText = LAT1CTOWX(mParameters[p].name.c_str()); item = new wxStaticText(w, 0, labelText + wxT(":")); item->SetName(labelText); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); wxString fieldText; float value = mPlugin->getParameter(mParameters[p].identifier); toggles[p] = 0; combos[p] = 0; sliders[p] = 0; fields[p] = 0; if (mParameters[p].isQuantized && mParameters[p].quantizeStep == 1.0 && mParameters[p].minValue == 0.0 && mParameters[p].maxValue == 1.0) { toggles[p] = new wxCheckBox(w, p, wxT("")); toggles[p]->SetName(labelText); toggles[p]->SetValue(value > 0.5); gridSizer->Add(toggles[p], 0, wxALL, 5); ConnectFocus(toggles[p]); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); } else if (mParameters[p].isQuantized && mParameters[p].quantizeStep == 1.0 && !mParameters[p].valueNames.empty()) { wxArrayString choices; wxString selected; for (size_t i = 0; i < mParameters[p].valueNames.size(); ++i) { wxString choice = wxString (mParameters[p].valueNames[i].c_str(), wxConvISO8859_1); if (int(value - mParameters[p].minValue + 0.5) == i) { selected = choice; } choices.Add(choice); } combos[p] = new wxComboBox(w, p, selected, wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY); combos[p]->SetName(labelText); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(combos[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5); ConnectFocus(combos[p]); gridSizer->Add(1, 1, 0); } else { fieldText = Internat::ToDisplayString(value); fields[p] = new wxTextCtrl(w, p, fieldText); fields[p]->SetName(labelText); gridSizer->Add(fields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); ConnectFocus(fields[p]); wxString str = Internat::ToDisplayString(mParameters[p].minValue); item = new wxStaticText(w, 0, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); sliders[p] = new wxSlider(w, p, 0, 0, 1000, wxDefaultPosition, wxSize(100, -1)); sliders[p]->SetName(labelText); gridSizer->Add(sliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5); ConnectFocus(sliders[p]); str = Internat::ToDisplayString(mParameters[p].maxValue); item = new wxStaticText(w, 0, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5); } } // Set all of the sliders based on the value in the // text fields inSlider = false; // Now we're ready for HandleText to actually do something. HandleText(); paramSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5); w->SetSizer(paramSizer); Layout(); Fit(); SetSizeHints(GetSize()); }
bool wxRibbonButtonBar::TryCollapseLayout(wxRibbonButtonBarLayout* original, size_t first_btn, size_t* last_button) { size_t btn_count = m_buttons.Count(); size_t btn_i; int used_height = 0; int used_width = 0; int available_width = 0; int available_height = 0; for(btn_i = first_btn + 1; btn_i > 0; /* decrement is inside loop */) { --btn_i; wxRibbonButtonBarButtonBase* button = m_buttons.Item(btn_i); wxRibbonButtonBarButtonState large_size_class = button->GetLargestSize(); wxSize large_size = button->sizes[large_size_class].size; int t_available_height = wxMax(available_height, large_size.GetHeight()); int t_available_width = available_width + large_size.GetWidth(); wxRibbonButtonBarButtonState small_size_class = large_size_class; if(!button->GetSmallerSize(&small_size_class)) { return false; } wxSize small_size = button->sizes[small_size_class].size; int t_used_height = used_height + small_size.GetHeight(); int t_used_width = wxMax(used_width, small_size.GetWidth()); if(t_used_height > t_available_height) { ++btn_i; break; } else { used_height = t_used_height; used_width = t_used_width; available_width = t_available_width; available_height = t_available_height; } } if(btn_i >= first_btn || used_width >= available_width) { return false; } if(last_button != NULL) { *last_button = btn_i; } wxRibbonButtonBarLayout* layout = new wxRibbonButtonBarLayout; WX_APPEND_ARRAY(layout->buttons, original->buttons); wxPoint cursor(layout->buttons.Item(btn_i).position); bool preserve_height = false; if(btn_i == 0) { // If height isn't preserved (i.e. it is reduced), then the minimum // size for the button bar will decrease, preventing the original // layout from being used (in some cases). // It may be a good idea to always preserve the height, but for now // it is only done when the first button is involved in a collapse. preserve_height = true; } for(; btn_i <= first_btn; ++btn_i) { wxRibbonButtonBarButtonInstance& instance = layout->buttons.Item(btn_i); instance.base->GetSmallerSize(&instance.size); instance.position = cursor; cursor.y += instance.base->sizes[instance.size].size.GetHeight(); } int x_adjust = available_width - used_width; for(; btn_i < btn_count; ++btn_i) { wxRibbonButtonBarButtonInstance& instance = layout->buttons.Item(btn_i); instance.position.x -= x_adjust; } layout->CalculateOverallSize(); // Sanity check if(layout->overall_size.GetWidth() >= original->overall_size.GetWidth() || layout->overall_size.GetHeight() > original->overall_size.GetHeight()) { delete layout; wxFAIL_MSG("Layout collapse resulted in increased size"); return false; } if(preserve_height) { layout->overall_size.SetHeight(original->overall_size.GetHeight()); } m_layouts.Add(layout); return true; }
//********************************************************************************* // draw pressure scale //********************************************************************************* void DashboardInstrument_BaroHistory::DrawWindSpeedScale(wxGCDC* dc) { wxString label1,label2,label3,label4,label5; wxColour cl; int width, height; cl=wxColour(61,61,204,255); dc->SetTextForeground(cl); dc->SetFont(*g_pFontSmall); //round m_MaxPress up to the next hpa ... if (m_MaxPress > 1100) m_MaxPress=1100; if (m_TotalMinPress < 930) m_TotalMinPress=930; m_MaxPressScale= (int)((m_MaxPress+15)-(m_TotalMinPress-15)); if(!m_IsRunning) { label1=_T("-- hPa"); label2=_T("-- hPa"); label3=_T("-- hPa"); label4=_T("-- hPa"); label5=_T("-- hPa"); } else { /* The goal is to draw the legend with decimals only, if we really have them ! */ // top legend for max press label1.Printf(_T("%.0f hPa"), m_MaxPressScale +(m_TotalMinPress-18) ); // 3/4 legend label2.Printf(_T("%.0f hPa"), m_MaxPressScale *3./4 + (m_TotalMinPress-18) ); // center legend label3.Printf(_T("%.0f hPa"), m_MaxPressScale /2 +(m_TotalMinPress-18)); // 1/4 legend label4.Printf(_T("%.0f hPa"), m_MaxPressScale /4 +(m_TotalMinPress-18) ); //bottom legend for min wind label5.Printf(_T("%.0f hPa"), (m_TotalMinPress-18)); } dc->GetTextExtent(label1, &m_LeftLegend, &height, 0, 0, g_pFontSmall); dc->DrawText(label1, 4, (int)(m_TopLineHeight-height/2)); dc->GetTextExtent(label2, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label2, 4, (int)(m_TopLineHeight+m_DrawAreaRect.height/4-height/2)); m_LeftLegend = wxMax(width,m_LeftLegend); dc->GetTextExtent(label3, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label3, 4, (int)(m_TopLineHeight+m_DrawAreaRect.height/2-height/2)); m_LeftLegend = wxMax(width,m_LeftLegend); dc->GetTextExtent(label4, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label4, 4, (int)(m_TopLineHeight+m_DrawAreaRect.height*0.75-height/2)); m_LeftLegend = wxMax(width,m_LeftLegend); dc->GetTextExtent(label5, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label5, 4, (int)(m_TopLineHeight+m_DrawAreaRect.height-height/2)); m_LeftLegend = wxMax(width,m_LeftLegend); m_LeftLegend+=4; }
void HexEditorCtrl::OnResize( wxSizeEvent &event ){ int x = event.GetSize().GetX(); int y = event.GetSize().GetY(); int charx = hex_ctrl->GetCharSize().GetX(); int chartx = text_ctrl->GetCharSize().GetX(); int offset_x = offset_ctrl->GetCharSize().GetX()*offset_ctrl->GetLineSize();// + 4; offset_x = offset_ctrl->IsShown() ? offset_x : 0; x -= offset_x; //Remove Offset Control box X because its changeable x -= offset_scroll_real->GetSize().GetX(); //Remove Offset scroll size x -= 4*2; //+x 4 pixel external borders (dark ones, 2 pix each size) x = wxMax(0,x); //Avoid X being negative y -= m_static_byteview->GetSize().GetY(); //Remove Head Text Y //AutoFill: bool custom_hex_format; wxConfig::Get()->Read( wxT("UseCustomHexFormat"), &custom_hex_format, false ); wxString fmt(wxT("xx ")); if( custom_hex_format ) wxConfig::Get()->Read( wxT("CustomHexFormat"), &fmt, wxT("xx ")); // TODO (death#1#): Move style engine somewhere else to speedy resizing. hex_ctrl->SetFormat( fmt ); int cnt_chr=0; //Counted character at current format for( unsigned i = 0 ; i < fmt.Len() ; i++ ){ if( fmt[i]!=' ' ) cnt_chr++; } cnt_chr/=2; // divide 2 for find byte per hex representation. int hexchr=0,textchr = 0; //Recalculate available area due hidden panels. hexchr+=hex_ctrl->IsShown() ? fmt.Len() : 0; textchr+=text_ctrl->IsShown() ? cnt_chr : 0; int available_space=0; available_space=x/(hexchr*charx+textchr*chartx/(GetCharToHexSize()/2)); //Limiting Bytes Per Line bool use_BytesPerLineLimit; wxConfig::Get()->Read( wxT("UseBytesPerLineLimit"), &use_BytesPerLineLimit, false ); if( use_BytesPerLineLimit ){ int BytesPerLineLimit; wxConfig::Get()->Read( wxT("BytesPerLineLimit"), reinterpret_cast<int*>(&BytesPerLineLimit), 16); //Downsizing is available if( available_space*cnt_chr > BytesPerLineLimit ) available_space = BytesPerLineLimit/cnt_chr; } //Calculation of available area for Hex and Text panels. int text_x = chartx*available_space*cnt_chr/(GetCharToHexSize()/2) +2 +4; int hex_x = charx*available_space*fmt.Len() +2 +4 - charx ; //no need for last gap; int ByteShownPerLine=available_space*cnt_chr; text_x = text_ctrl->IsShown() ? text_x : 0; hex_x = hex_ctrl->IsShown() ? hex_x : 0; #ifdef _DEBUG_SIZE_ std::cout<< "HexEditorCtrl::OnResize()" << std::endl << "HexEditorCtrl SizeEvent ReSize Command=(" << event.GetSize().GetX() << ',' << event.GetSize().GetY() << ")\n" << "Offset Scrll: \t(" << offset_scroll->GetSize().GetX() << ',' << event.GetSize().GetY() <<")\n" << "Offset Ctrl: \t(" << offset_ctrl->GetSize().GetX() << ',' << event.GetSize().GetY() <<")\n" << "Hex Ctrl: \t(" << hex_x << ',' << event.GetSize().GetY() << ")\n" << "Text Ctrl: \t(" << text_x << ',' << event.GetSize().GetY() << ")\n" << "Hex Char: \t" << charx << std::endl << "ByteShownPerLine: \t" << ByteShownPerLine << std::endl; #endif offset_ctrl->SetMinSize( wxSize( offset_x , y ) ); // offset_ctrl->SetSize( wxSize( offset_x , y ) ); //Not needed, Layout() Makes the job well. m_static_offset->SetMinSize( wxSize(offset_x, m_static_offset->GetSize().GetY()) ); hex_ctrl->SetMinSize( wxSize( hex_x, y )); // hex_ctrl->SetSize( wxSize( hex_x, y )); m_static_address->SetMinSize( wxSize(hex_x, m_static_offset->GetSize().GetY()) ) ; text_ctrl->SetMinSize( wxSize( text_x, y )); // text_ctrl->SetSize( wxSize( text_x, y )); m_static_byteview->SetMinSize( wxSize( text_x, m_static_offset->GetSize().GetY()) ); // Destroy the sizer created by the form builder before adding the windows // managed by it to another sizer, otherwise we would crash later when // destroying the sizer as it wouldn't know about the windows it contains. SetSizer(NULL); //Preparing Sizer wxFlexGridSizer* fgSizer1 = new wxFlexGridSizer( 2, 4, 0, 0 ); #if 1 fgSizer1->Add( m_static_offset, 0, wxALIGN_CENTER|wxLEFT, 5 ); fgSizer1->Add( m_static_address, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 2 ); fgSizer1->Add( m_static_byteview, 0, wxALIGN_CENTER|wxALL, 0 ); fgSizer1->Add( m_static_null, 0, wxALIGN_CENTER, 3 ); fgSizer1->Add( offset_ctrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 0 ); fgSizer1->Add( hex_ctrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 0 ); fgSizer1->Add( text_ctrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 0 ); fgSizer1->Add( offset_scroll_real, 0, wxEXPAND, 0 ); #else fgSizer1->Add( m_static_offset, 0, wxALIGN_CENTER|wxLEFT, 0 ); fgSizer1->Add( m_static_address, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL|wxLEFT, 0 ); fgSizer1->Add( m_static_byteview, 0, wxALIGN_CENTER|wxALL, 0 ); fgSizer1->Add( m_static_null, 0, wxALIGN_CENTER, 0 ); fgSizer1->Add( offset_ctrl, 0, wxALIGN_CENTER|wxALL|wxEXPAND, 0 ); fgSizer1->Add( hex_ctrl, 0, wxALIGN_CENTER|wxALL, 0 ); fgSizer1->Add( text_ctrl, 0, wxALIGN_CENTER|wxALL|wxEXPAND, 0 ); fgSizer1->Add( offset_scroll_real, 0, wxEXPAND, 0 ); fgSizer1->AddGrowableCol(1,1); // fgSizer1->AddGrowableRow(1,1); #endif this->SetSizer( fgSizer1 ); this->Layout(); #ifdef __WXMSW__ ///At windows, OnResize cannot update required fields immeditialy, this hack fixes this behaviour. hex_ctrl->ChangeSize(); text_ctrl->ChangeSize(); offset_ctrl->ChangeSize(); #endif //Formating Hex and byteview column labels //This needed bellow hex_ctrl->ChangeSize() because it's updates the IsDenied function. wxString address,byteview,temp_address; for( int j = 0 ; j < ByteShownPerLine ; j++ ){ temp_address << wxString::Format( wxT("%02X"), j%0x100 ); //if(j >= ByteShownPerLine/(GetCharToHexSize()/2)) // continue; byteview << wxString::Format( wxT("%01X"), (j*(GetCharToHexSize()/2))%0x10 ); } //Adjusting custom hex formatting bar - Converting 00010203 -> 00 01 02 03 for "xx " format. for( int x = 0, i=0 ; x < hex_x && static_cast<unsigned>(i) < temp_address.Len() ; x++ ) if(hex_ctrl->IsDenied(x)) address << wxT(" "); else address << temp_address[i++]; m_static_address->SetLabel(address); m_static_byteview->SetLabel( byteview ); #ifdef _DEBUG_SIZE_ std::cout<< "HexEditorCtrl After ReSize=(" << x << ',' << y << ")\n" << "Offset Scrll: \t(" << offset_scroll->GetSize().GetX() << ',' << offset_scroll->GetSize().GetY()<<")\n" << "Offset Ctrl: \t(" << offset_ctrl->GetSize().GetX() << ',' << offset_ctrl->GetSize().GetY()<<")\n" << "Hex Ctrl: \t(" << hex_ctrl->GetSize().GetX() << ',' << hex_ctrl->GetSize().GetY()<<")\n" << "Text Ctrl: \t(" << text_ctrl->GetSize().GetX() << ',' << text_ctrl->GetSize().GetY()<<")\n"; #endif }
TCWin::TCWin( ChartCanvas *parent, int x, int y, void *pvIDX ) { // As a display optimization.... // if current color scheme is other than DAY, // Then create the dialog ..WITHOUT.. borders and title bar. // This way, any window decorations set by external themes, etc // will not detract from night-vision m_created = false; xSpot = 0; ySpot = 0; m_pTCRolloverWin = NULL; long wstyle = wxCLIP_CHILDREN | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ; if( ( global_color_scheme != GLOBAL_COLOR_SCHEME_DAY ) && ( global_color_scheme != GLOBAL_COLOR_SCHEME_RGB ) ) wstyle |= ( wxNO_BORDER ); #ifdef __WXOSX__ wstyle |= wxSTAY_ON_TOP; #endif pParent = parent; m_x = x; m_y = y; RecalculateSize(); wxDialog::Create( parent, wxID_ANY, wxString( _T ( "" ) ), m_position , m_tc_size, wstyle ); m_created = true; wxFont *qFont = GetOCPNScaledFont(_("Dialog")); SetFont( *qFont ); pIDX = (IDX_entry *) pvIDX; gpIDXn++; // Set up plot type if( strchr( "Tt", pIDX->IDX_type ) ) { m_plot_type = TIDE_PLOT; SetTitle( wxString( _( "Tide" ) ) ); gpIDX = pIDX; // remember pointer for routeplan } else { m_plot_type = CURRENT_PLOT; SetTitle( wxString( _( "Current" ) ) ); } int sx, sy; GetClientSize( &sx, &sy ); // Figure out this computer timezone minute offset wxDateTime this_now = gTimeSource; bool cur_time = !gTimeSource.IsValid(); if (cur_time) { this_now = wxDateTime::Now(); } wxDateTime this_gmt = this_now.ToGMT(); #if wxCHECK_VERSION(2, 6, 2) wxTimeSpan diff = this_now.Subtract( this_gmt ); #else wxTimeSpan diff = this_gmt.Subtract ( this_now ); #endif int diff_mins = diff.GetMinutes(); // Correct a bug in wx3.0.2 // If the system TZ happens to be GMT, with DST active (e.g.summer in London), // then wxDateTime returns incorrect results for toGMT() method #if wxCHECK_VERSION(3, 0, 2) if( diff_mins == 0 && this_now.IsDST() ) diff_mins +=60; #endif int station_offset = ptcmgr->GetStationTimeOffset( pIDX ); m_corr_mins = station_offset - diff_mins; if( this_now.IsDST() ) m_corr_mins += 60; // Establish the inital drawing day as today m_graphday = this_now; wxDateTime graphday_00 = this_now; graphday_00.ResetTime(); time_t t_graphday_00 = graphday_00.GetTicks(); // Correct a Bug in wxWidgets time support if( !graphday_00.IsDST() && m_graphday.IsDST() ) t_graphday_00 -= 3600; if( graphday_00.IsDST() && !m_graphday.IsDST() ) t_graphday_00 += 3600; m_t_graphday_00_at_station = t_graphday_00 - ( m_corr_mins * 60 ); btc_valid = false; wxString* TClist = NULL; m_tList = new wxListBox( this, -1, wxPoint( sx * 65 / 100, 11 ), wxSize( ( sx * 32 / 100 ), ( sy * 20 / 100 ) ), 0, TClist, wxLB_SINGLE | wxLB_NEEDED_SB | wxLB_HSCROLL ); // Measure the size of a generic button, with label wxButton *test_button = new wxButton( this, wxID_OK, _( "OK" ), wxPoint( -1, -1), wxDefaultSize ); test_button->GetSize( &m_tsx, &m_tsy ); delete test_button; // In the interest of readability, if the width of the dialog is too narrow, // simply skip showing the "Hi/Lo" list control. if( (m_tsy * 15) > sx ) m_tList->Hide(); OK_button = new wxButton( this, wxID_OK, _( "OK" ), wxPoint( sx - (2 * m_tsy + 10), sy - (m_tsy + 10) ), wxDefaultSize ); PR_button = new wxButton( this, ID_TCWIN_PR, _( "Prev" ), wxPoint( 10, sy - (m_tsy + 10) ), wxSize( -1, -1 ) ); wxSize texc_size = wxSize( ( sx * 60 / 100 ), ( sy *29 / 100 ) ); if( !m_tList->IsShown()){ texc_size = wxSize( ( sx * 90 / 100 ), ( sy *29 / 100 ) ); } m_ptextctrl = new wxTextCtrl( this, -1, _T(""), wxPoint( sx * 3 / 100, 6 ), texc_size , wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); int bsx, bsy, bpx, bpy; PR_button->GetSize( &bsx, &bsy ); PR_button->GetPosition( &bpx, &bpy ); NX_button = new wxButton( this, ID_TCWIN_NX, _( "Next" ), wxPoint( bpx + bsx + 5, sy - (m_tsy + 10) ), wxSize( -1, -1 ) ); m_TCWinPopupTimer.SetOwner( this, TCWININF_TIMER ); wxScreenDC dc; int text_height; dc.GetTextExtent(_T("W"), NULL, &text_height); m_button_height = m_tsy; //text_height + 20; // Build graphics tools wxFont *dlg_font = FontMgr::Get().GetFont( _("Dialog") ); int dlg_font_size = dlg_font->GetPointSize(); pSFont = FontMgr::Get().FindOrCreateFont( dlg_font_size-2, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, FALSE, wxString( _T ( "Arial" ) ) ); pSMFont = FontMgr::Get().FindOrCreateFont( dlg_font_size-1, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, FALSE, wxString( _T ( "Arial" ) ) ); pMFont = FontMgr::Get().FindOrCreateFont( dlg_font_size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, FALSE, wxString( _T ( "Arial" ) ) ); pLFont = FontMgr::Get().FindOrCreateFont( dlg_font_size+1, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, FALSE, wxString( _T ( "Arial" ) ) ); pblack_1 = wxThePenList->FindOrCreatePen( GetGlobalColor( _T ( "UINFD" ) ), wxMax(1,(int)(m_tcwin_scaler+0.5)), wxPENSTYLE_SOLID ); pblack_2 = wxThePenList->FindOrCreatePen( GetGlobalColor( _T ( "UINFD" ) ), wxMax(2,(int)(2*m_tcwin_scaler+0.5)), wxPENSTYLE_SOLID ); pblack_3 = wxThePenList->FindOrCreatePen( GetGlobalColor( _T ( "UWHIT" ) ), wxMax(1,(int)(m_tcwin_scaler+0.5)), wxPENSTYLE_SOLID ); pred_2 = wxThePenList->FindOrCreatePen( GetGlobalColor( _T ( "UINFR" ) ), wxMax(4,(int)(4*m_tcwin_scaler+0.5)), wxPENSTYLE_SOLID ); pltgray = wxTheBrushList->FindOrCreateBrush( GetGlobalColor( _T ( "UIBCK" ) ), wxBRUSHSTYLE_SOLID ); pltgray2 = wxTheBrushList->FindOrCreateBrush( GetGlobalColor( _T ( "DILG1" ) ), wxBRUSHSTYLE_SOLID ); DimeControl( this ); // Fill in some static text control information // Tidi station information m_ptextctrl->Clear(); wxString locn( pIDX->IDX_station_name, wxConvUTF8 ); wxString locna, locnb; if( locn.Contains( wxString( _T ( "," ) ) ) ) { locna = locn.BeforeFirst( ',' ); locnb = locn.AfterFirst( ',' ); } else { locna = locn; locnb.Empty(); } // write the first line wxTextAttr style; style.SetFont( *pLFont ); m_ptextctrl->SetDefaultStyle( style ); m_ptextctrl->AppendText( locna ); m_ptextctrl->AppendText(_T("\n")); style.SetFont( *pSMFont ); m_ptextctrl->SetDefaultStyle( style ); if( !locnb.IsEmpty() ) m_ptextctrl->AppendText( locnb ); m_ptextctrl->AppendText(_T("\n")); //Reference to the master station if(( 't' == pIDX->IDX_type ) || ( 'c' == pIDX->IDX_type )) { wxString mref( pIDX->IDX_reference_name, wxConvUTF8 ); mref.Prepend(_T(" ")); m_ptextctrl->AppendText( _( "Reference Station :" ) ); m_ptextctrl->AppendText(_T("\n")); m_ptextctrl->AppendText( mref ); m_ptextctrl->AppendText(_T("\n")); } else { m_ptextctrl->AppendText(_T("\n")); } // Show the data source wxString dsource( pIDX->source_ident, wxConvUTF8 ); dsource.Prepend(_T(" ")); m_ptextctrl->AppendText( _( "Data Source :" ) ); m_ptextctrl->AppendText(_T("\n")); m_ptextctrl->AppendText( dsource ); m_ptextctrl->ShowPosition( 0 ); }
void __CALL_CONVENTION endCallback(void) { // Create a TriPrim char buf[40]; if(s_nvcall > s_nvmax) // keep track of largest number of triangle vertices s_nvmax = s_nvcall; switch(s_gltri_type) { case GL_TRIANGLE_FAN: case GL_TRIANGLE_STRIP: case GL_TRIANGLES: { TriPrim *pTPG = new TriPrim; if(NULL == s_pTPG_Last) { s_pTPG_Head = pTPG; s_pTPG_Last = pTPG; } else { s_pTPG_Last->p_next = pTPG; s_pTPG_Last = pTPG; } pTPG->p_next = NULL; pTPG->type = s_gltri_type; pTPG->nVert = s_nvcall; // Calculate bounding box float sxmax = -1000; // this poly BBox float sxmin = 1000; float symax = -90; float symin = 90; GLdouble *pvr = s_pwork_buf; for(int iv=0 ; iv < s_nvcall ; iv++) { GLdouble xd, yd; xd = *pvr++; yd = *pvr++; if(s_bmerc_transform) { double valx = ( xd * s_transform_x_rate ) + s_transform_x_origin; double valy = ( yd * s_transform_y_rate ) + s_transform_y_origin; // Convert to lat/lon double lat = ( 2.0 * atan ( exp ( valy/CM93_semimajor_axis_meters ) ) - PI/2. ) / DEGREE; double lon = ( valx / ( DEGREE * CM93_semimajor_axis_meters ) ); sxmax = wxMax(lon, sxmax); sxmin = wxMin(lon, sxmin); symax = wxMax(lat, symax); symin = wxMin(lat, symin); } else { sxmax = wxMax(xd, sxmax); sxmin = wxMin(xd, sxmin); symax = wxMax(yd, symax); symin = wxMin(yd, symin); } } pTPG->tri_box.Set(symin, sxmin, symax, sxmax); // Transcribe this geometry to TriPrim, converting to SM if called for if(s_bSENC_SM) { GLdouble *pds = s_pwork_buf; pTPG->p_vertex = (double *)malloc(s_nvcall * 2 * sizeof(double)); GLdouble *pdd = (GLdouble*)pTPG->p_vertex; for(int ip = 0 ; ip < s_nvcall ; ip++) { double dlon = *pds++; double dlat = *pds++; double easting, northing; toSM(dlat, dlon, s_ref_lat, s_ref_lon, &easting, &northing); *pdd++ = easting; *pdd++ = northing; } } else { pTPG->p_vertex = (double *)malloc(s_nvcall * 2 * sizeof(double)); memcpy(pTPG->p_vertex, s_pwork_buf, s_nvcall * 2 * sizeof(double)); } break; } default: { sprintf(buf, "....begin Callback unknown\n"); break; } } }
LV2EffectDialog::LV2EffectDialog(LV2Effect *effect, wxWindow *parent, const LilvPlugin *data, int sampleRate, double length, double WXUNUSED(noteLength), unsigned char WXUNUSED(noteVelocity), unsigned char WXUNUSED(noteKey)) : wxDialog(parent, wxID_ANY, mEffect->GetString(lilv_plugin_get_name(data)), wxDefaultPosition, wxSize(500, -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), mEffect(effect), mData(data), mControls(effect->GetControls()), mSampleRate(sampleRate), mLength(length) { #if defined(__WXMSW__) // On Windows, for some reason, wxWindows calls OnTextCtrl during creation // of the text control, and LV2EffectDialog::OnTextCtrl calls HandleText, // which assumes all the mFields have been initialized. // This can give us a bad pointer crash, so manipulate inSlider to // no-op HandleText during creation. inSlider = true; #else inSlider = false; #endif inText = false; inText = true; // Allocate memory for the user parameter controls int ctrlcnt = (int) mControls.GetCount(); mToggles = new wxCheckBox*[ctrlcnt]; mSliders = new wxSlider*[ctrlcnt]; mFields = new wxTextCtrl*[ctrlcnt]; mLabels = new wxStaticText*[ctrlcnt]; mEnums = new wxChoice*[ctrlcnt]; wxControl *item; wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL); // Add information about the plugin LilvNode *tmpValue = lilv_plugin_get_author_name(data); if (tmpValue) { wxString author(_("Author: ") + mEffect->GetString(tmpValue)); item = new wxStaticText(this, wxID_ANY, author); vSizer->Add(item, 0, wxALL, 5); lilv_node_free(tmpValue); } wxScrolledWindow *w = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxTAB_TRAVERSAL); // Try to give the window a sensible default/minimum size w->SetMinSize(wxSize( wxMax(600, parent->GetSize().GetWidth() * 2/3), parent->GetSize().GetHeight() / 2)); w->SetScrollRate(0, 20); vSizer->Add(w, 1, wxEXPAND|wxALL, 5); // Preview, OK, & Cancel buttons vSizer->Add(CreateStdButtonSizer(this, ePreviewButton|eCancelButton|eOkButton), 0, wxEXPAND); SetSizer(vSizer); wxSizer *paramSizer = new wxStaticBoxSizer(wxVERTICAL, w, _("Effect Settings")); wxFlexGridSizer *gridSizer = new wxFlexGridSizer(5, 0, 0); gridSizer->AddGrowableCol(3); // Now add the length control if (mEffect->GetEffectFlags() & INSERT_EFFECT) { item = new wxStaticText(w, 0, _("Length (seconds)")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); mSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length)); mSeconds->SetName(_("Length (seconds)")); gridSizer->Add(mSeconds, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mSeconds); } // The note controls if the plugin is a synth if (mEffect->IsSynth()) { // Note length control item = new wxStaticText(w, wxID_ANY, _("Note length (seconds)")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); mNoteSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length / 2)); mNoteSeconds->SetName(_("Note length (seconds)")); gridSizer->Add(mNoteSeconds, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mNoteSeconds); // Note velocity control item = new wxStaticText(w, wxID_ANY, _("Note velocity")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); mNoteVelocity = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(64)); mNoteVelocity->SetName(_("Note velocity")); gridSizer->Add(mNoteVelocity, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mNoteVelocity); // Note key control item = new wxStaticText(w, wxID_ANY, _("Note key")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); mNoteKey = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(64)); mNoteKey->SetName(_("Note key")); gridSizer->Add(mNoteKey, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mNoteKey); } paramSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5); // Create user parameter controls std::queue<const LV2PortGroup *> groups; groups.push(&mEffect->GetRootGroup()); while (!groups.empty()) { const LV2PortGroup* pg = groups.front(); groups.pop(); if (pg->GetName() != wxEmptyString) { wxSizer *groupSizer = new wxStaticBoxSizer(wxVERTICAL, w, pg->GetName()); paramSizer->Add(groupSizer, 0, wxEXPAND | wxALL, 5); gridSizer = new wxFlexGridSizer(5, 0, 0); gridSizer->AddGrowableCol(3); groupSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5); } const LV2PortGroupArray & subgroups = pg->GetSubGroups(); LV2PortGroupArray::const_iterator si; for (si = subgroups.begin(); si != subgroups.end(); si++) { if ((*si)->GetParameters().GetCount() != 0) { groups.push(*si); } } const wxArrayInt & params = pg->GetParameters(); for (size_t pi = 0; pi < params.GetCount(); pi++) { int p = params[pi]; if (p >= ctrlcnt) { continue; } LV2Port & port = mControls[p]; wxString labelText = port.mName; item = new wxStaticText(w, 0, labelText + wxT(":")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); wxString fieldText; if (port.mToggle) { mToggles[p] = new wxCheckBox(w, p, wxT("")); mToggles[p]->SetName(labelText); mToggles[p]->SetValue(port.mControlBuffer > 0); gridSizer->Add(mToggles[p], 0, wxALL, 5); ConnectFocus(mToggles[p]); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); } else if (port.mEnumeration) { mEnums[p] = new wxChoice(w, p); mEnums[p]->SetName(labelText); mEnums[p]->Append(port.mScaleLabels); int s; for (s = (int) port.mScaleValues.GetCount() - 1; s >= 0; s--) { if (port.mControlBuffer >= port.mScaleValues[s]) { break; } } if (s < 0) { s = 0; } mEnums[p]->SetSelection(s); gridSizer->Add(mEnums[p], 0, wxALL | wxEXPAND, 5); ConnectFocus(mEnums[p]); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); } else { if (port.mInteger) { fieldText.Printf(wxT("%d"), (int)(port.mControlBuffer + 0.5)); } else { fieldText = Internat::ToDisplayString(port.mControlBuffer); } mFields[p] = new wxTextCtrl(w, p, fieldText); mFields[p]->SetName(labelText); gridSizer->Add(mFields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); ConnectFocus(mFields[p]); wxString bound; double lower = 0.0; double upper = 0.0; bool haslo = false; bool hashi = false; bool forceint = false; wxString loLabel; wxString hiLabel; #if 0 ScalePointMap::const_iterator iter = scalePoints.find(port.mIndex); if (!wxNaN(port.mMin)) { lower = port.mMin; haslo = true; if (iter != scalePoints.end()) { std::map<float, wxString>::const_iterator iter2 = iter->second.find(lower); if (iter2 != iter->second.end()) { loLabel = iter2->second; } } } if (!isnan(port.mMax)) { upper = port.mMax; hashi = true; if (iter != scalePoints.end()) { std::map<float, wxString>::const_iterator iter2 = iter->second.find(upper); if (iter2 != iter->second.end()) { hiLabel = iter2->second; } } } #endif if (port.mSampleRate) { lower *= mSampleRate * 1000; upper *= mSampleRate; forceint = true; } wxString str; if (haslo) { str = loLabel; if (str.IsEmpty()) { if (port.mInteger || forceint) { str.Printf(wxT("%d"), (int)(lower + 0.5)); } else { str = Internat::ToDisplayString(lower); } } item = new wxStaticText(w, wxID_ANY, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); } else { gridSizer->Add(1, 1, 0); } mSliders[p] = new wxSlider(w, p, 0, 0, 1000, wxDefaultPosition, wxSize(200, -1)); mSliders[p]->SetName(labelText); gridSizer->Add(mSliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5); ConnectFocus(mSliders[p]); if (hashi) { str = hiLabel; if (str.IsEmpty()) { if (port.mInteger || forceint) { str.Printf(wxT("%d"), (int)(upper + 0.5)); } else { str = Internat::ToDisplayString(upper); } } item = new wxStaticText(w, wxID_ANY, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5); } else { gridSizer->Add(1, 1, 0); } } } } // Set all of the mSliders based on the value in the // text mFields inSlider = false; // Now we're ready for HandleText to actually do something. HandleText(); w->SetSizer(paramSizer); Layout(); Fit(); SetSizeHints(GetSize()); }
void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags) { int i; wxRadioButton *current; // define the position int x_current, y_current; int x_offset, y_offset; int widthOld, heightOld; GetSize( &widthOld, &heightOld ); GetPosition( &x_current, &y_current ); x_offset = x; y_offset = y; if (!(sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) { if (x == wxDefaultCoord) x_offset = x_current; if (y == wxDefaultCoord) y_offset = y_current; } // define size int charWidth, charHeight; int maxWidth, maxHeight; int eachWidth[128], eachHeight[128]; int totWidth, totHeight; GetTextExtent( wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), &charWidth, &charHeight ); charWidth /= 52; maxWidth = -1; maxHeight = -1; wxSize bestSizeRadio ; if ( m_radioButtonCycle ) bestSizeRadio = m_radioButtonCycle->GetBestSize(); for (unsigned int i = 0 ; i < m_noItems; i++) { GetTextExtent(GetString(i), &eachWidth[i], &eachHeight[i] ); eachWidth[i] = eachWidth[i] + RADIO_SIZE; eachHeight[i] = wxMax( eachHeight[i], bestSizeRadio.y ); if (maxWidth < eachWidth[i]) maxWidth = eachWidth[i]; if (maxHeight < eachHeight[i]) maxHeight = eachHeight[i]; } // according to HIG (official space - 3 Pixels Diff between Frame and Layout size) int space = 3; if ( GetWindowVariant() == wxWINDOW_VARIANT_MINI ) space = 2; totHeight = GetRowCount() * maxHeight + (GetRowCount() - 1) * space; totWidth = GetColumnCount() * (maxWidth + charWidth); wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) ) ; // change the width / height only when specified if ( width == wxDefaultCoord ) { if ( sizeFlags & wxSIZE_AUTO_WIDTH ) width = sz.x; else width = widthOld; } if ( height == wxDefaultCoord ) { if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) height = sz.y; else height = heightOld; } wxControl::DoSetSize( x_offset, y_offset, width, height, wxSIZE_AUTO ); // arrange radio buttons int x_start, y_start; x_start = ( width - sz.x ) / 2; y_start = ( height - sz.y ) / 2; x_offset = x_start; y_offset = y_start; current = m_radioButtonCycle; for (i = 0 ; i < (int)m_noItems; i++) { // not to do for the zero button! if ((i > 0) && ((i % GetMajorDim()) == 0)) { if (m_windowStyle & wxRA_SPECIFY_ROWS) { x_offset += maxWidth + charWidth; y_offset = y_start; } else { x_offset = x_start; y_offset += maxHeight + space; } } current->SetSize( x_offset, y_offset, eachWidth[i], eachHeight[i] ); current = current->NextInCycle(); if (m_windowStyle & wxRA_SPECIFY_ROWS) y_offset += maxHeight + space; else x_offset += maxWidth + charWidth; } }
void GutterCtrl::OnMouseLeftDown(wxMouseEvent& event) { //wxLogDebug("OnMouseLeftDown"); //wxASSERT(m_editorCtrl); wxASSERT(m_currentSel == -1); Lines& lines = m_editorCtrl.GetLines(); // Get Mouse location const int x = event.GetX(); const int y = event.GetY() + m_editorCtrl.GetYScrollPos(); // Handle bookmarks if (m_showBookmarks && x < (int)m_numberX) { // Find out which line was clicked on if ((int)y < lines.GetHeight()) { const unsigned int line_id = lines.GetLineFromYPos(y); m_editorCtrl.AddBookmark(line_id, true /*toggle*/); DrawGutter(); // Redraw gutter to show bookmarks return; } } // Handle folding if (m_showFolds && x > (int)m_foldStartX) { ClickOnFold(y); return; } bool hasSelection = false; interval sel(0, 0); if (event.ShiftDown() && lines.IsSelected()) { sel = lines.GetSelections()[lines.GetLastSelection()]; hasSelection = true; } // If not multiselecting or extending, remove previous selections if (!event.ControlDown()) { lines.RemoveAllSelections(); } // Find out which line was clicked on if (y < lines.GetHeight()) { const unsigned int line_id = lines.GetLineFromYPos(y); // Select the line if (!lines.isLineVirtual(line_id)) { int startpos = lines.GetLineStartpos(line_id); int endpos = lines.GetLineEndpos(line_id, false); if (hasSelection) { startpos = wxMin(startpos, (int)sel.start); endpos = wxMax(endpos, (int)sel.end); } m_currentSel = lines.AddSelection(startpos, endpos); lines.SetPos(endpos); m_editorCtrl.SetFocus(); m_sel_startline = m_sel_endline = line_id; } m_sel_startoutside = false; } else { const unsigned int linecount = lines.GetLineCount(); m_sel_startline = m_sel_endline = linecount ? linecount-1 : 0; m_sel_startoutside = true; if (hasSelection) { m_currentSel = lines.AddSelection(sel.start, lines.GetLength()); lines.SetPos(lines.GetLength()); m_editorCtrl.SetFocus(); } } // Make sure we capure all mouse events // this is released in OnMouseLeftUp() CaptureMouse(); // Redraw the editCtrl to show new selection m_editorCtrl.DrawLayout(); }
void GutterCtrl::OnMouseMotion(wxMouseEvent& event) { Lines& lines = m_editorCtrl.GetLines(); // Get Mouse location const int y = event.GetY() + m_editorCtrl.GetYScrollPos(); if (event.LeftIsDown() && HasCapture()) { // Find out what is under mouse unsigned int line_id; if (y < 0) line_id = 0; else if (y < lines.GetHeight()) { line_id = lines.GetLineFromYPos(y); } else { if (m_sel_startoutside && m_currentSel != -1) { // Make sure we remove current selection m_currentSel = lines.UpdateSelection(m_currentSel, 0, 0); lines.SetPos(lines.GetLength()); m_editorCtrl.DrawLayout(); return; } const unsigned int linecount = lines.GetLineCount(); line_id = linecount ? linecount-1 : 0; } // Select the lines if (line_id != m_sel_endline) { m_sel_endline = line_id; int sel_start = lines.GetLineStartpos(wxMin(m_sel_startline, m_sel_endline)); int sel_end = lines.GetLineEndpos(wxMax(m_sel_startline, m_sel_endline), false); if (sel_start == sel_end) { lines.RemoveAllSelections(); m_currentSel = -1; } else { // Update the lines selection info if (m_currentSel == -1) { m_currentSel = lines.AddSelection(sel_start, sel_end); } else { m_currentSel = lines.UpdateSelection(m_currentSel, sel_start, sel_end); } lines.SetPos(m_sel_endline < m_sel_startline ? sel_start : sel_end); } m_editorCtrl.MakeCaretVisible(); // also ensures scrolling if outside window m_editorCtrl.DrawLayout(); } } else if (event.GetX() > (int)m_foldStartX && 0 <=y && y < lines.GetHeight()) { const unsigned int line_id = lines.GetLineFromYPos(y); vector<cxFold*> foldStack = m_editorCtrl.GetFoldStack(line_id); if (!foldStack.empty()) { m_currentFold = foldStack.back(); DrawGutter(); // Redraw gutter to show highlights return; } } if (m_currentFold) { m_currentFold = NULL; DrawGutter(); // Redraw gutter to remove highlights } }
// Build the calibration "step" graph which will appear on the lefthand side of the panels wxBitmap CalReviewDialog::CreateGraph(bool AO) { wxMemoryDC memDC; wxBitmap bmp(CALREVIEW_BITMAP_SIZE, CALREVIEW_BITMAP_SIZE, -1); wxPen axisPen("GREY", 3, wxCROSS_HATCH); wxColour raColor = pFrame->pGraphLog->GetRaOrDxColor(); wxColour decColor = pFrame->pGraphLog->GetDecOrDyColor(); wxPen raPen(raColor, 3, wxSOLID); wxPen decPen(decColor, 3, wxSOLID); wxBrush raBrush(raColor, wxSOLID); wxBrush decBrush(decColor, wxSOLID); CalibrationDetails calDetails; double scaleFactor; int ptRadius; if (!pSecondaryMount) { pMount->GetCalibrationDetails(&calDetails); // Normal case, no AO } else { if (AO) { pMount->GetCalibrationDetails(&calDetails); // AO tab, use AO details } else { pSecondaryMount->GetCalibrationDetails(&calDetails); // Mount tab, use mount details } } // Find the max excursion from the origin in order to scale the points to fit the bitmap double biggestVal = -100.0; for (std::vector<wxRealPoint>::const_iterator it = calDetails.raSteps.begin(); it != calDetails.raSteps.end(); ++it) { biggestVal = wxMax(biggestVal, fabs(it->x)); biggestVal = wxMax(biggestVal, fabs(it->y)); } for (std::vector<wxRealPoint>::const_iterator it = calDetails.decSteps.begin(); it != calDetails.decSteps.end(); ++it) { biggestVal = wxMax(biggestVal, fabs(it->x)); biggestVal = wxMax(biggestVal, fabs(it->y)); } if (biggestVal > 0.0) scaleFactor = ((CALREVIEW_BITMAP_SIZE - 5) / 2) / biggestVal; // Leave room for circular point else scaleFactor = 1.0; memDC.SelectObject(bmp); memDC.SetBackground(*wxBLACK_BRUSH); memDC.Clear(); memDC.SetPen(axisPen); // Draw the axes memDC.SetDeviceOrigin(wxCoord(CALREVIEW_BITMAP_SIZE / 2), wxCoord(CALREVIEW_BITMAP_SIZE / 2)); memDC.DrawLine(-CALREVIEW_BITMAP_SIZE / 2, 0, CALREVIEW_BITMAP_SIZE / 2, 0); // x memDC.DrawLine(0, -CALREVIEW_BITMAP_SIZE / 2, 0, CALREVIEW_BITMAP_SIZE / 2); // y if (calDetails.raStepCount > 0) { // Draw the RA data memDC.SetPen(raPen); memDC.SetBrush(raBrush); ptRadius = 2; // Scale the points, then plot them individually for (int i = 0; i < (int) calDetails.raSteps.size(); i++) { if (i == calDetails.raStepCount + 2) // Valid even for "single-step" calibration { memDC.SetPen(wxPen(raColor, 1)); // 1-pixel-thick outline memDC.SetBrush(wxNullBrush); // Outline only for "return" data points ptRadius = 3; } memDC.DrawCircle(IntPoint(calDetails.raSteps.at(i), scaleFactor), ptRadius); } // Show the line PHD2 will use for the rate memDC.SetPen(raPen); if ((int)calDetails.raSteps.size() > calDetails.raStepCount) // New calib, includes return values memDC.DrawLine(IntPoint(calDetails.raSteps.at(0), scaleFactor), IntPoint(calDetails.raSteps.at(calDetails.raStepCount), scaleFactor)); else memDC.DrawLine(IntPoint(calDetails.raSteps.at(0), scaleFactor), IntPoint(calDetails.raSteps.at(calDetails.raStepCount - 1), scaleFactor)); } // Handle the Dec data memDC.SetPen(decPen); memDC.SetBrush(decBrush); ptRadius = 2; if (calDetails.decStepCount > 0) { for (int i = 0; i < (int) calDetails.decSteps.size(); i++) { if (i == calDetails.decStepCount + 2) { memDC.SetPen(wxPen(decColor, 1)); // 1-pixel-thick outline memDC.SetBrush(wxNullBrush); // Outline only for "return" data points ptRadius = 3; } memDC.DrawCircle(IntPoint(calDetails.decSteps.at(i), scaleFactor), ptRadius); } // Show the line PHD2 will use for the rate memDC.SetPen(decPen); if ((int)calDetails.decSteps.size() > calDetails.decStepCount) // New calib, includes return values memDC.DrawLine(IntPoint(calDetails.decSteps.at(0), scaleFactor), IntPoint(calDetails.decSteps.at(calDetails.decStepCount), scaleFactor)); else memDC.DrawLine(IntPoint(calDetails.decSteps.at(0), scaleFactor), IntPoint(calDetails.decSteps.at(calDetails.decStepCount - 1), scaleFactor)); } memDC.SelectObject(wxNullBitmap); return bmp; }
//********************************************************************************* // draw wind speed scale //********************************************************************************* void TacticsInstrument_WindDirHistory::DrawWindSpeedScale(wxGCDC* dc) { wxString label1, label2, label3, label4, label5; wxColour cl; int width, height; double val1; double WindSpdScale; cl = wxColour(61, 61, 204, 255); dc->SetTextForeground(cl); dc->SetFont(*g_pFontSmall); //round maxWindSpd up to the next full knot; nicer view ... m_MaxWindSpdScale = (int)m_MaxWindSpd + 1; if (!m_IsRunning) { label1.Printf(_T("--- %s"), m_WindSpeedUnit.c_str()); label2 = label1; label3 = label1; label4 = label1; label5 = label1; } else { /*we round the speed up to the next full knot ==> the top and bottom line have full numbers as legend (e.g. 23 kn -- 0 kn) but the intermediate lines may have decimal values (e.g. center line : 23/2=11.5 or quarter line 23/4=5.75), so in worst case we end up with 23 - 17.25 - 11.5 - 5.75 - 0 The goal is to draw the legend with decimals only, if we really have them ! */ // top legend for max wind label1.Printf(_T("%.0f %s"), toUsrSpeed_Plugin(m_MaxWindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); // 3/4 legend WindSpdScale = m_MaxWindSpdScale*3. / 4.; // do we need a decimal ? val1 = (int)((WindSpdScale - (int)WindSpdScale) * 100); if (val1 == 25 || val1 == 75) // it's a .25 or a .75 label2.Printf(_T("%.2f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); else if (val1 == 50) label2.Printf(_T("%.1f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); else label2.Printf(_T("%.0f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); // center legend WindSpdScale = m_MaxWindSpdScale / 2.; // center line can either have a .0 or .5 value ! if ((int)(WindSpdScale * 10) % 10 == 5) label3.Printf(_T("%.1f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); else label3.Printf(_T("%.0f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); // 1/4 legend WindSpdScale = m_MaxWindSpdScale / 4.; // do we need a decimal ? val1 = (int)((WindSpdScale - (int)WindSpdScale) * 100); if (val1 == 25 || val1 == 75) label4.Printf(_T("%.2f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); else if (val1 == 50) label4.Printf(_T("%.1f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); else label4.Printf(_T("%.0f %s"), toUsrSpeed_Plugin(WindSpdScale, g_iDashWindSpeedUnit), m_WindSpeedUnit.c_str()); //bottom legend for min wind, always 0 label5.Printf(_T("%.0f %s"), 0.0, m_WindSpeedUnit.c_str()); } dc->GetTextExtent(label1, &m_LeftLegend, &height, 0, 0, g_pFontSmall); dc->DrawText(label1, 4, (int)(m_TopLineHeight - height / 2)); dc->GetTextExtent(label2, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label2, 4, (int)(m_TopLineHeight + m_DrawAreaRect.height / 4 - height / 2)); m_LeftLegend = wxMax(width, m_LeftLegend); dc->GetTextExtent(label3, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label3, 4, (int)(m_TopLineHeight + m_DrawAreaRect.height / 2 - height / 2)); m_LeftLegend = wxMax(width, m_LeftLegend); dc->GetTextExtent(label4, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label4, 4, (int)(m_TopLineHeight + m_DrawAreaRect.height*0.75 - height / 2)); m_LeftLegend = wxMax(width, m_LeftLegend); dc->GetTextExtent(label5, &width, &height, 0, 0, g_pFontSmall); dc->DrawText(label5, 4, (int)(m_TopLineHeight + m_DrawAreaRect.height - height / 2)); m_LeftLegend = wxMax(width, m_LeftLegend); m_LeftLegend += 4; }
//********************************************************************************* // wind direction legend //********************************************************************************* void TacticsInstrument_WindDirHistory::DrawWindDirScale(wxGCDC* dc) { wxString label1, label2, label3, label4, label5; wxColour cl; wxPen pen; int width, height; cl = wxColour(204, 41, 41, 255); //red, opague dc->SetTextForeground(cl); dc->SetFont(*g_pFontSmall); if (!m_IsRunning) { label1 = _T("---"); label2 = _T("---"); label3 = _T("---"); label4 = _T("---"); label5 = _T("---"); } else { // label 1 : legend for bottom line. By definition always w/o decimals double tempdir = m_MinWindDir; while (tempdir < 0) tempdir += 360; while (tempdir >= 360) tempdir -= 360; label1 = GetWindDirStr(wxString::Format(_T("%.1f"), tempdir)); // label 2 : 1/4 tempdir = m_MinWindDir + m_WindDirRange / 4.; while (tempdir < 0) tempdir += 360; while (tempdir >= 360) tempdir -= 360; label2 = GetWindDirStr(wxString::Format(_T("%.1f"), tempdir)); // label 3 : legend for center line tempdir = m_MinWindDir + m_WindDirRange / 2; while (tempdir < 0) tempdir += 360; while (tempdir >= 360) tempdir -= 360; label3 = GetWindDirStr(wxString::Format(_T("%.1f"), tempdir)); // label 4 : 3/4 tempdir = m_MinWindDir + m_WindDirRange*0.75; while (tempdir < 0) tempdir += 360; while (tempdir >= 360) tempdir -= 360; label4 = GetWindDirStr(wxString::Format(_T("%.1f"), tempdir)); // label 5 : legend for top line tempdir = m_MaxWindDir; while (tempdir < 0) tempdir += 360; while (tempdir >= 360) tempdir -= 360; label5 = GetWindDirStr(wxString::Format(_T("%.1f"), tempdir)); } //draw the legend with the labels; find the widest string and store it in m_RightLegend. // m_RightLegend is the basis for the horizontal lines ! dc->GetTextExtent(label5, &width, &height, 0, 0, g_pFontSmall); m_RightLegend = width; dc->GetTextExtent(label4, &width, &height, 0, 0, g_pFontSmall); m_RightLegend = wxMax(width, m_RightLegend); dc->GetTextExtent(label3, &width, &height, 0, 0, g_pFontSmall); m_RightLegend = wxMax(width, m_RightLegend); dc->GetTextExtent(label2, &width, &height, 0, 0, g_pFontSmall); m_RightLegend = wxMax(width, m_RightLegend); dc->GetTextExtent(label1, &width, &height, 0, 0, g_pFontSmall); m_RightLegend = wxMax(width, m_RightLegend); m_RightLegend += 4; //leave some space to the edge dc->DrawText(label5, m_WindowRect.width - m_RightLegend, m_TopLineHeight - height / 2); dc->DrawText(label4, m_WindowRect.width - m_RightLegend, (int)(m_TopLineHeight + m_DrawAreaRect.height / 4 - height / 2)); dc->DrawText(label3, m_WindowRect.width - m_RightLegend, (int)(m_TopLineHeight + m_DrawAreaRect.height / 2 - height / 2)); dc->DrawText(label2, m_WindowRect.width - m_RightLegend, (int)(m_TopLineHeight + m_DrawAreaRect.height*0.75 - height / 2)); dc->DrawText(label1, m_WindowRect.width - m_RightLegend, (int)(m_TopLineHeight + m_DrawAreaRect.height - height / 2)); }
void Styler_SearchHL::Style(StyleRun& sr) { const unsigned int rstart = sr.GetRunStart(); const unsigned int rend = sr.GetRunEnd(); // Style the run with search ranges for (vector<interval>::const_iterator r = m_searchRanges.begin(); r != m_searchRanges.end(); ++r) { if (r->end > rstart && r->start < rend) { unsigned int start = wxMax(rstart, r->start); unsigned int end = wxMin(rend, r->end); sr.SetBackgroundColor(start, end, m_rangeColor); } } // No need for more styling if no search text if (m_text.empty()) return; // Extend stylerun start/end to get better search results (round up to whole EXTSIZEs) unsigned int sr_start = rstart> 100 ? rstart - 100 : 0; const unsigned int ext_end = ((rend/EXTSIZE) * EXTSIZE) + EXTSIZE; unsigned int sr_end = ext_end < m_lines.GetLength() ? ext_end : m_lines.GetLength(); // Make sure the extended positions are valid cxLOCKDOC_READ(m_doc) sr_start = doc.GetValidCharPos(sr_start); if (sr_end != m_lines.GetLength()) sr_end = doc.GetValidCharPos(sr_end); cxENDLOCK //wxLogDebug("Style %u %u", rstart, rend); //wxLogDebug(" %u %u - %u %u", sr_start, sr_end, m_search_start, m_search_end); // Check if we need to do a new search if (sr_start < m_search_start || m_search_end < sr_end) { // Check if there is overlap so we can just extend the search area if (sr_end > m_search_start && sr_start < m_search_end) { sr_start = wxMin(sr_start, m_search_start); sr_end = wxMax(sr_end, m_search_end); } else { // Else we have to move it m_matches.clear(); m_search_start = 0; m_search_end = 0; } // Do the search if (sr_start < m_search_start) { // Search from top DoSearch(sr_start, sr_end); } else if (sr_end > m_search_end) { // Search from bottom DoSearch(sr_start, sr_end, true); } else wxASSERT(false); m_search_start = sr_start; m_search_end = sr_end; } // Style the run with matches for (vector<interval>::iterator p = m_matches.begin(); p != m_matches.end(); ++p) { if (p->start > rend) break; // Check for overlap (or zero-length sel at start-of-line) if ((p->end > rstart && p->start < rend) || (p->start == p->end && p->end == rstart)) { unsigned int start = wxMax(rstart, p->start); unsigned int end = wxMin(rend, p->end); // Only draw it if it is in range if (!m_searchRanges.empty()) { bool inRange = false; for (vector<interval>::const_iterator s = m_searchRanges.begin(); s != m_searchRanges.end(); ++s) { if (start >= s->start && start < s->end) { inRange = true; break; } } if (!inRange) continue; } ApplyStyle(sr, start, end); } } }
// Layout algorithm for any window. mainWindow gets what's left over. bool wxLayoutAlgorithm::LayoutWindow(wxWindow* parent, wxWindow* mainWindow) { // Test if the parent is a sash window, and if so, // reduce the available space to allow space for any active edges. int leftMargin = 0, rightMargin = 0, topMargin = 0, bottomMargin = 0; #if wxUSE_SASH if (wxDynamicCast(parent, wxSashWindow)) { wxSashWindow* sashWindow = (wxSashWindow*) parent; leftMargin = sashWindow->GetExtraBorderSize(); rightMargin = sashWindow->GetExtraBorderSize(); topMargin = sashWindow->GetExtraBorderSize(); bottomMargin = sashWindow->GetExtraBorderSize(); if (sashWindow->GetSashVisible(wxSASH_LEFT)) leftMargin += sashWindow->GetDefaultBorderSize(); if (sashWindow->GetSashVisible(wxSASH_RIGHT)) rightMargin += sashWindow->GetDefaultBorderSize(); if (sashWindow->GetSashVisible(wxSASH_TOP)) topMargin += sashWindow->GetDefaultBorderSize(); if (sashWindow->GetSashVisible(wxSASH_BOTTOM)) bottomMargin += sashWindow->GetDefaultBorderSize(); } #endif // wxUSE_SASH int cw, ch; parent->GetClientSize(& cw, & ch); wxRect rect(leftMargin, topMargin, cw - leftMargin - rightMargin, ch - topMargin - bottomMargin); wxCalculateLayoutEvent event; event.SetRect(rect); // Find the last layout-aware window, so we can make it fill all remaining // space. wxWindow *lastAwareWindow = NULL; wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst(); while (node) { wxWindow* win = node->GetData(); if (win->IsShown()) { wxCalculateLayoutEvent tempEvent(win->GetId()); tempEvent.SetEventObject(win); tempEvent.SetFlags(wxLAYOUT_QUERY); tempEvent.SetRect(event.GetRect()); if (win->GetEventHandler()->ProcessEvent(tempEvent)) lastAwareWindow = win; } node = node->GetNext(); } // Now do a dummy run to see if we have any space left for the final window (fail if not) node = parent->GetChildren().GetFirst(); while (node) { wxWindow* win = node->GetData(); // If mainWindow is NULL and we're at the last window, // skip this, because we'll simply make it fit the remaining space. if (win->IsShown() && (win != mainWindow) && (mainWindow != NULL || win != lastAwareWindow)) { event.SetId(win->GetId()); event.SetEventObject(win); event.SetFlags(wxLAYOUT_QUERY); win->GetEventHandler()->ProcessEvent(event); } node = node->GetNext(); } if (event.GetRect().GetWidth() < 0 || event.GetRect().GetHeight() < 0) return false; event.SetRect(rect); node = parent->GetChildren().GetFirst(); while (node) { wxWindow* win = node->GetData(); // If mainWindow is NULL and we're at the last window, // skip this, because we'll simply make it fit the remaining space. if (win->IsShown() && (win != mainWindow) && (mainWindow != NULL || win != lastAwareWindow)) { event.SetId(win->GetId()); event.SetEventObject(win); event.SetFlags(0); // ?? win->GetEventHandler()->ProcessEvent(event); } node = node->GetNext(); } rect = event.GetRect(); if (mainWindow) mainWindow->SetSize(rect.x, rect.y, wxMax(0, rect.width), wxMax(0, rect.height)); else if (lastAwareWindow) { // Fit the remaining space lastAwareWindow->SetSize(rect.x, rect.y, wxMax(0, rect.width), wxMax(0, rect.height)); } return true; }
void TCWin::OnPaint( wxPaintEvent& event ) { int x, y; int i; char sbuf[100]; int w; float tcmax, tcmin; if(m_graph_rect.x == 0) return; GetClientSize( &x, &y ); // qDebug() << "OnPaint" << x << y; #if 0 // establish some graphic element sizes/locations int x_graph = x * 1 / 10; int y_graph = y * 32 / 100; int x_graph_w = x * 8 / 10; int y_graph_h = (y * .7) - (3 * m_button_height); m_graph_rect = wxRect(x_graph, y_graph, x_graph_w, y_graph_h); wxSize texc_size = wxSize( ( x * 60 / 100 ), ( y *29 / 100 ) ); if( !m_tList->IsShown()){ texc_size = wxSize( ( x * 90 / 100 ), ( y *29 / 100 ) ); } m_ptextctrl->SetSize(texc_size); #endif wxPaintDC dc( this ); wxString tlocn( pIDX->IDX_station_name, wxConvUTF8 ); // if(1/*bForceRedraw*/) { int x_textbox = x * 5 / 100; int y_textbox = 6; int x_textbox_w = x * 51 / 100; int y_textbox_h = y * 25 / 100; // box the location text & tide-current table dc.SetPen( *pblack_3 ); dc.SetBrush( *pltgray2 ); dc.DrawRoundedRectangle( x_textbox, y_textbox, x_textbox_w, y_textbox_h, 4 ); //location text box if(m_tList->IsShown()) { wxRect tab_rect = m_tList->GetRect(); dc.DrawRoundedRectangle( tab_rect.x - 4, y_textbox, tab_rect.width + 8, y_textbox_h, 4 ); //tide-current table box } // Box the graph dc.SetPen( *pblack_1 ); dc.SetBrush( *pltgray ); dc.DrawRectangle( m_graph_rect.x, m_graph_rect.y, m_graph_rect.width, m_graph_rect.height ); // On some platforms, we cannot draw rotated text. // So, reduce the complexity of horizontal axis time labels #ifndef __WXMSW__ const int hour_delta = 4; #else const int hour_delta = 1; #endif // Horizontal axis dc.SetFont( *pSFont ); for( i = 0; i < 25; i++ ) { int xd = m_graph_rect.x + ( ( i ) * m_graph_rect.width / 25 ); if( hour_delta != 1 ){ if( i % hour_delta == 0 ) { dc.SetPen( *pblack_2 ); dc.DrawLine( xd, m_graph_rect.y, xd, m_graph_rect.y + m_graph_rect.height + 5 ); char sbuf[5]; sprintf( sbuf, "%02d", i ); int x_shim = -20; dc.DrawText( wxString( sbuf, wxConvUTF8 ), xd + x_shim + ( m_graph_rect.width / 25 ) / 2, m_graph_rect.y + m_graph_rect.height + 8 ); } else { dc.SetPen( *pblack_1 ); dc.DrawLine( xd, m_graph_rect.y, xd, m_graph_rect.y + m_graph_rect.height + 5 ); } } else { dc.SetPen( *pblack_1 ); dc.DrawLine( xd, m_graph_rect.y, xd, m_graph_rect.y + m_graph_rect.height + 5 ); wxString sst; sst.Printf( _T("%02d"), i ); dc.DrawRotatedText( sst, xd + ( m_graph_rect.width / 25 ) / 2, m_graph_rect.y + m_graph_rect.height + 8, 270. ); } } // Make a line for "right now" wxDateTime this_now = gTimeSource; bool cur_time = !gTimeSource.IsValid(); if (cur_time) this_now = wxDateTime::Now(); time_t t_now = this_now.GetTicks(); // now, in ticks float t_ratio = m_graph_rect.width * ( t_now - m_t_graphday_00_at_station ) / ( 25 * 3600.0f ); //must eliminate line outside the graph (in that case put it outside the window) int xnow = ( t_ratio < 0 || t_ratio > m_graph_rect.width ) ? -1 : m_graph_rect.x + (int) t_ratio; dc.SetPen( *pred_2 ); dc.DrawLine( xnow, m_graph_rect.y, xnow, m_graph_rect.y + m_graph_rect.height ); dc.SetPen( *pblack_1 ); // Build the array of values, capturing max and min and HW/LW list if( !btc_valid ) { float dir; tcmax = -10; tcmin = 10; float val; m_tList->Clear(); int list_index = 0; bool wt; wxBeginBusyCursor(); // get tide flow sens ( flood or ebb ? ) ptcmgr->GetTideFlowSens( m_t_graphday_00_at_station, BACKWARD_ONE_HOUR_STEP, pIDX->IDX_rec_num, tcv[0], val, wt ); for( i = 0; i < 26; i++ ) { int tt = m_t_graphday_00_at_station + ( i * FORWARD_ONE_HOUR_STEP ); ptcmgr->GetTideOrCurrent( tt, pIDX->IDX_rec_num, tcv[i], dir ); tt_tcv[i] = tt; // store the corresponding time_t value if( tcv[i] > tcmax ) tcmax = tcv[i]; if( tcv[i] < tcmin ) tcmin = tcv[i]; if( TIDE_PLOT == m_plot_type ) { if( !( ( tcv[i] > val ) == wt ) ) // if tide flow sens change { float tcvalue; //look backward for HW or LW time_t tctime; ptcmgr->GetHightOrLowTide( tt, BACKWARD_TEN_MINUTES_STEP, BACKWARD_ONE_MINUTES_STEP, tcv[i], wt, pIDX->IDX_rec_num, tcvalue, tctime ); wxDateTime tcd; //write date wxString s, s1; tcd.Set( tctime + ( m_corr_mins * 60 ) ); s.Printf( tcd.Format( _T("%H:%M ") ) ); s1.Printf( _T("%05.2f "), tcvalue ); //write value s.Append( s1 ); Station_Data *pmsd = pIDX->pref_sta_data; //write unit if( pmsd ) s.Append( wxString( pmsd->units_abbrv, wxConvUTF8 ) ); s.Append( _T(" ") ); ( wt ) ? s.Append( _("HW") ) : s.Append( _("LW") ); //write HW or LT m_tList->Insert( s, list_index ); // update table list list_index++; wt = !wt; //change tide flow sens } val = tcv[i]; } if( CURRENT_PLOT == m_plot_type ) { wxDateTime thx; //write date wxString s, s1; thx.Set( (time_t) ( tt + ( m_corr_mins * 60 ) ) ); s.Printf( thx.Format( _T("%H:%M ") ) ); s1.Printf( _T("%05.2f "), fabs( tcv[i] ) ); //write value s.Append( s1 ); Station_Data *pmsd = pIDX->pref_sta_data; //write unit if( pmsd ) s.Append( wxString( pmsd->units_abbrv, wxConvUTF8 ) ); s1.Printf( _T(" %03.0f"), dir ); //write direction s.Append( s1 ); m_tList->Insert( s, list_index ); // update table list list_index++; } } wxEndBusyCursor(); // Set up the vertical parameters based on Tide or Current plot if( CURRENT_PLOT == m_plot_type ) { it = __max ( abs (( int ) tcmin - 1 ), abs ( ( int ) tcmax + 1 ) ); ib = -it; im = 2 * it; m_plot_y_offset = m_graph_rect.height / 2; val_off = 0; } else { ib = (int) tcmin; if( tcmin < 0 ) ib -= 1; it = (int) tcmax + 1; im = it - ib; //abs ( ib ) + abs ( it ); m_plot_y_offset = ( m_graph_rect.height * ( it - ib ) ) / im; val_off = ib; } // Arrange to skip some lines and legends if there are too many for the vertical space we have int height_stext; dc.GetTextExtent( _T("1"), NULL, &height_stext ); float available_lines = (float) m_graph_rect.height / height_stext; i_skip = (int) ceil(im / available_lines); if( CURRENT_PLOT == m_plot_type && i_skip != 1) { // Adjust steps so slack current "0" line is always drawn on graph ib -= it % i_skip; it = -ib; im = 2 * it; } // Build spline list of points m_sList.DeleteContents( true ); m_sList.Clear(); for( i = 0; i < 26; i++ ) { wxPoint *pp = new wxPoint; pp->x = m_graph_rect.x + ( ( i ) * m_graph_rect.width / 25 ); pp->y = m_graph_rect.y + ( m_plot_y_offset ) - (int) ( ( tcv[i] - val_off ) * m_graph_rect.height / im ); m_sList.Append( pp ); } btc_valid = true; } dc.SetTextForeground( GetGlobalColor( _T ( "DILG3" ) ) ); // Vertical Axis i = ib; while( i < it + 1 ) { int yd = m_graph_rect.y + ( m_plot_y_offset ) - ( ( i - val_off ) * m_graph_rect.height / im ); if( ( m_plot_y_offset + m_graph_rect.y ) == yd ) dc.SetPen( *pblack_2 ); else dc.SetPen( *pblack_1 ); dc.DrawLine( m_graph_rect.x, yd, m_graph_rect.x + m_graph_rect.width, yd ); snprintf( sbuf, 99, "%d", i ); dc.DrawText( wxString( sbuf, wxConvUTF8 ), m_graph_rect.x - 20, yd - 5 ); i += i_skip; } // Draw the Value curve #if wxCHECK_VERSION(2, 9, 0) wxPointList *list = (wxPointList *)&m_sList; #else wxList *list = (wxList *) &m_sList; #endif dc.SetPen( *pblack_2 ); #if wxUSE_SPLINES dc.DrawSpline( list ); #else dc.DrawLines ( list ); #endif // More Info /// int station_offset = ptcmgr->GetStationTimeOffset( pIDX ); int h = station_offset / 60; int m = station_offset - ( h * 60 ); if( m_graphday.IsDST() ) h += 1; m_stz.Printf( _T("UTC %+03d:%02d"), h, m ); // Make the "nice" (for the US) station time-zone string, brutally by hand double lat = ptcmgr->GetStationLat(pIDX); if( lat > 20.0 ){ wxString mtz; switch( ptcmgr->GetStationTimeOffset( pIDX ) ) { case -240: mtz = _T( "AST" ); break; case -300: mtz = _T( "EST" ); break; case -360: mtz = _T( "CST" ); break; } if( mtz.Len() ) { if( m_graphday.IsDST() ) mtz[1] = 'D'; m_stz = mtz; } } dc.SetFont( *pSFont ); dc.GetTextExtent( m_stz, &w, &h ); dc.DrawText( m_stz, x / 2 - w / 2, y - 2.5 * m_button_height ); wxString sdate; if(g_locale == _T("en_US")) sdate = m_graphday.Format( _T ( "%A %b %d, %Y" ) ); else sdate = m_graphday.Format( _T ( "%A %d %b %Y" ) ); dc.SetFont( *pMFont ); dc.GetTextExtent( sdate, &w, &h ); dc.DrawText( sdate, x / 2 - w / 2, y - 2.0 * m_button_height ); Station_Data *pmsd = pIDX->pref_sta_data; if( pmsd ) { dc.GetTextExtent( wxString( pmsd->units_conv, wxConvUTF8 ), &w, &h ); dc.DrawRotatedText( wxString( pmsd->units_conv, wxConvUTF8 ), 5, m_graph_rect.y + m_graph_rect.height / 2 + w / 2, 90. ); } // Show flood and ebb directions if(( strchr( "c", pIDX->IDX_type ) ) || ( strchr( "C", pIDX->IDX_type ) )) { dc.SetFont( *pSFont ); wxString fdir; fdir.Printf( _T("%03d"), pIDX->IDX_flood_dir ); dc.DrawText( fdir, m_graph_rect.x + m_graph_rect.width + 4, m_graph_rect.y + m_graph_rect.height * 1 / 4 ); wxString edir; edir.Printf( _T("%03d"), pIDX->IDX_ebb_dir ); dc.DrawText( edir, m_graph_rect.x + m_graph_rect.width + 4, m_graph_rect.y + m_graph_rect.height * 3 / 4 ); } // Today or tomorrow if( (m_button_height * 15) < x && cur_time){ // large enough horizontally? wxString sday; int day = m_graphday.GetDayOfYear(); if( m_graphday.GetYear() == this_now.GetYear() ) { if( day == this_now.GetDayOfYear() ) sday.Append( _( "Today" ) ); else if( day == this_now.GetDayOfYear() + 1 ) sday.Append( _( "Tomorrow" ) ); else sday.Append( m_graphday.GetWeekDayName( m_graphday.GetWeekDay() ) ); } else if( m_graphday.GetYear() == this_now.GetYear() + 1 && day == this_now.Add( wxTimeSpan::Day() ).GetDayOfYear() ) sday.Append( _( "Tomorrow" ) ); dc.SetFont( *pSFont ); dc.GetTextExtent( sday, &w, &h ); dc.DrawText( sday, 55 - w / 2, y - 2 * m_button_height ); } // Render "Spot of interest" double spotDim = 4 * g_Platform->GetDisplayDPmm(); dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( GetGlobalColor( _T ( "YELO1" ) ), wxBRUSHSTYLE_SOLID ) ); dc.SetPen( wxPen( GetGlobalColor( _T ( "URED" ) ), wxMax(2, 0.5 * g_Platform->GetDisplayDPmm()) ) ); dc.DrawRoundedRectangle(xSpot - spotDim/2, ySpot - spotDim/2, spotDim, spotDim, spotDim/2); dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( GetGlobalColor( _T ( "UBLCK" ) ), wxBRUSHSTYLE_SOLID ) ); dc.SetPen( wxPen( GetGlobalColor( _T ( "UBLCK" ) ), 1 ) ); double ispotDim = spotDim / 5.; dc.DrawRoundedRectangle(xSpot - ispotDim/2, ySpot - ispotDim/2, ispotDim, ispotDim, ispotDim/2); } }
static int RangeCheck(int thisval) { return wxMin(wxMax(thisval, 0), (int) ProfileWizard::STATE_DONE); }
LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, wxWindow * parent, const LADSPA_Descriptor *data, float *inputControls, int sampleRate, double length) :wxDialog(parent, -1, LAT1CTOWX(data->Name), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), effect(eff) { mLength = length; numParams = 0; this->mData = data; this->inputControls = inputControls; this->sampleRate = sampleRate; #ifdef __WXMSW__ // On Windows, for some reason, wxWindows calls OnTextCtrl during creation // of the text control, and LadspaEffectDialog::OnTextCtrl calls HandleText, // which assumes all the fields have been initialized. // This can give us a bad pointer crash, so manipulate inSlider to // no-op HandleText during creation. inSlider = true; #else inSlider = false; #endif inText = false; toggles = new wxCheckBox*[mData->PortCount]; sliders = new wxSlider*[mData->PortCount]; fields = new wxTextCtrl*[mData->PortCount]; labels = new wxStaticText*[mData->PortCount]; ports = new unsigned long [mData->PortCount]; unsigned long p; for(p=0; p<mData->PortCount; p++) { LADSPA_PortDescriptor d = mData->PortDescriptors[p]; if (LADSPA_IS_PORT_CONTROL(d) && LADSPA_IS_PORT_INPUT(d)) { ports[numParams] = p; numParams++; } } wxControl *item; wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL); if (mData->Maker && mData->Maker[0] && LAT1CTOWX(mData->Maker) != wxString(_("None"))) { item = new wxStaticText(this, 0, wxString(_("Author: "))+LAT1CTOWX(mData->Maker)); vSizer->Add(item, 0, wxALL, 5); } if (mData->Copyright && mData->Copyright[0] && LAT1CTOWX(mData->Copyright) != wxString(_("None"))) { item = new wxStaticText(this, 0, LAT1CTOWX(mData->Copyright)); vSizer->Add(item, 0, wxALL, 5); } wxScrolledWindow *w = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxTAB_TRAVERSAL); // Try to give the window a sensible default/minimum size w->SetMinSize(wxSize( wxMax(600, parent->GetSize().GetWidth() * 2/3), parent->GetSize().GetHeight() / 2)); w->SetScrollRate(0, 20); vSizer->Add(w, 1, wxEXPAND|wxALL, 5); // Preview, OK, & Cancel buttons vSizer->Add(CreateStdButtonSizer(this, ePreviewButton|eCancelButton|eOkButton), 0, wxEXPAND); SetSizer(vSizer); wxSizer *paramSizer = new wxStaticBoxSizer(wxVERTICAL, w, _("Effect Settings")); wxFlexGridSizer *gridSizer = new wxFlexGridSizer(5, 0, 0); gridSizer->AddGrowableCol(3); for (p = 0; p < numParams; p++) { wxString labelText = LAT1CTOWX(mData->PortNames[ports[p]]); item = new wxStaticText(w, 0, labelText + wxT(":")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); wxString fieldText; LADSPA_PortRangeHint hint = mData->PortRangeHints[ports[p]]; if (LADSPA_IS_HINT_TOGGLED(hint.HintDescriptor)) { toggles[p] = new wxCheckBox(w, p, wxT("")); toggles[p]->SetName(labelText); toggles[p]->SetValue(inputControls[ports[p]] > 0); gridSizer->Add(toggles[p], 0, wxALL, 5); ConnectFocus(toggles[p]); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); } else { if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor)) fieldText.Printf(wxT("%d"), (int)(inputControls[ports[p]] + 0.5)); else fieldText = Internat::ToDisplayString(inputControls[ports[p]]); fields[p] = new wxTextCtrl(w, p, fieldText); fields[p]->SetName(labelText); gridSizer->Add(fields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); ConnectFocus(fields[p]); wxString bound; double lower = 0.0; double upper = 0.0; bool haslo = false; bool hashi = false; bool forceint = false; if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) { lower = hint.LowerBound; haslo = true; } if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) { upper = hint.UpperBound; hashi = true; } if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) { lower *= sampleRate * 1000; upper *= sampleRate; forceint = true; } wxString str; if (haslo) { if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint) str.Printf(wxT("%d"), (int)(lower + 0.5)); else str = Internat::ToDisplayString(lower); item = new wxStaticText(w, 0, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); } else { gridSizer->Add(1, 1, 0); } sliders[p] = new wxSlider(w, p, 0, 0, 1000, wxDefaultPosition, wxSize(200, -1)); sliders[p]->SetName(labelText); gridSizer->Add(sliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5); ConnectFocus(sliders[p]); if (hashi) { if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint) str.Printf(wxT("%d"), (int)(upper + 0.5)); else str = Internat::ToDisplayString(upper); item = new wxStaticText(w, 0, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5); } else { gridSizer->Add(1, 1, 0); } } } // Now add the length control if (effect->GetEffectFlags() & INSERT_EFFECT) { item = new wxStaticText(w, 0, _("Length (seconds)")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); mSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length)); mSeconds->SetName(_("Length (seconds)")); gridSizer->Add(mSeconds, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mSeconds); } // Set all of the sliders based on the value in the // text fields inSlider = false; // Now we're ready for HandleText to actually do something. HandleText(); paramSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5); w->SetSizer(paramSizer); Layout(); Fit(); SetSizeHints(GetSize()); }
void FixedLine::DrawLine(int xoffset, int yoffset, const wxRect& WXUNUSED(rect), bool isFolded) { wxASSERT(width > 0); // Style the lines m_sr.Init(textstart, textend); for (vector<Styler*>::iterator si = m_stylers.begin(); si != m_stylers.end(); ++si) { (*si)->Style(m_sr); } // Style with selections bool endstyle = false; for(vector<interval>::const_iterator iv = selections.begin(); iv != selections.end(); ++iv) { if((textstart < iv->end && iv->start < textend) || (iv->start == textstart && iv->end == textstart)) { // Calculate enclosed interval int s_start = wxMax(textstart, (*iv).start); int s_end = wxMin(textend, (*iv).end); const wxColour& useBackground = m_isSelShadow ? m_theme.shadowColor : m_theme.selectionColor; m_sr.SetBackgroundColor(s_start, s_end, useBackground); m_sr.SetShowHidden(s_start, s_end, true); } else if (iv->start == textend && iv->end == textend) { // We might have to draw a selection caret at the end endstyle = true; const wxColour& useBackground = m_isSelShadow ? m_theme.shadowColor : m_theme.selectionColor; m_sr.SetBackgroundColor(textend, textend, useBackground); } } // Highlight matching brackets (can only be single byte utf char) if (m_hlBracket.start < m_hlBracket.end) { if (m_hlBracket.start >= textstart && m_hlBracket.start < textend) { m_sr.SetFontStyle(m_hlBracket.start, m_hlBracket.start+1, wxFONTFLAG_BOLD); m_sr.SetBackgroundColor(m_hlBracket.start, m_hlBracket.start+1, m_theme.bracketHighlightColor); } if (m_hlBracket.end >= textstart && m_hlBracket.end < textend) { m_sr.SetFontStyle(m_hlBracket.end, m_hlBracket.end+1, wxFONTFLAG_BOLD); m_sr.SetBackgroundColor(m_hlBracket.end, m_hlBracket.end+1, m_theme.bracketHighlightColor); } } bool isIndent = true; unsigned int style_id = 0; unsigned int next_style_id = 0; unsigned int next_style_start = 0; unsigned int linestart = 0; int ypos = 0; const char* const buf = (const char*)m_lineBuffer.data(); for (vector<unsigned int>::iterator i = breakpoints.begin(); i != breakpoints.end(); ++i) { wxASSERT(ypos + charheight <= height); unsigned int breakpoint = *i; unsigned int segstart = linestart; int segoffset = 0; // Smart wrap if (m_indentWidth && i > breakpoints.begin()) { if (dc.GetBackgroundMode() != wxTRANSPARENT) { dc.SetPen(dc.GetTextBackground()); dc.SetBrush(wxBrush(dc.GetTextBackground(), wxSOLID)); dc.DrawRectangle(xoffset + segoffset, yoffset+ypos, m_indentWidth, charheight); } if (m_sr.ShowHidden(style_id)) { dc.SetBrush(wxBrush(m_theme.invisiblesColor, wxBDIAGONAL_HATCH)); dc.DrawRectangle(xoffset + segoffset, yoffset+ypos, m_indentWidth, charheight); } segoffset = m_indentWidth; } // if we are not wrapping we want to start at first visible char unsigned int pos = linestart; if (m_wrapMode == cxWRAP_NONE && xoffset < 0) { // find first visible char if (m_extents.back() < (unsigned int)-xoffset) segstart = pos = breakpoint; // no part of line visible (may clip newline) else { vector<unsigned int>::iterator p = lower_bound(m_extents.begin(), m_extents.end(), (unsigned int)-xoffset); linestart = segstart = pos = distance(m_extents.begin(), p); segoffset = pos ? m_extents[pos-1] : 0; style_id = m_sr.GetStyleAtPos(textstart + pos); next_style_id = style_id+1; next_style_start = m_sr.GetStyleEnd(style_id) - textstart; m_sr.ApplyStyle(style_id); } } for (const char* dbi = buf + linestart; pos < breakpoint; ++dbi, ++pos) { // Check for style change if (pos == next_style_start) { if (pos > segstart) { segoffset += DrawText(xoffset, segoffset, yoffset+ypos, segstart, pos); segstart = pos; } unsigned int style_end = m_sr.GetStyleEnd(next_style_id) - textstart; if (next_style_start == style_end) { // zero length style. Draw a caret and go to next style m_sr.ApplyStyle(next_style_id++); if (dc.GetTextBackground() != wxNullColour) { dc.SetPen(dc.GetTextBackground()); dc.SetBrush(wxBrush(dc.GetTextBackground(), wxSOLID)); dc.DrawRectangle(xoffset + segoffset, yoffset+ypos, 3, charheight); } next_style_start = m_sr.GetStyleEnd(next_style_id) - textstart; } else next_style_start = style_end; style_id = next_style_id++; m_sr.ApplyStyle(style_id); } // Check for special chars switch (*dbi) { case ' ': if (isIndent || m_sr.ShowHidden(style_id)) { if (pos > segstart) { segoffset += DrawText(xoffset, segoffset, yoffset+ypos, segstart, pos); } if (m_sr.ShowHidden(style_id)) { const unsigned int xpos = xoffset + segoffset; wxColour textcolor = dc.GetTextForeground(); // Buffer text color dc.SetTextForeground(m_theme.invisiblesColor); dc.DrawBitmap(bmSpace, xpos, yoffset+ypos, false); dc.SetTextForeground(textcolor); // Re-set text color } else if (dc.GetBackgroundMode() != wxTRANSPARENT) { dc.SetPen(dc.GetTextBackground()); dc.SetBrush(wxBrush(dc.GetTextBackground(), wxSOLID)); dc.DrawRectangle(xoffset + segoffset, yoffset+ypos, charwidth, charheight); } // Indent guides if (isIndent && m_showIndent && segoffset > 0 && IsTabPos(segstart)) { dc.SetPen(m_theme.invisiblesColor); for (unsigned int y = yoffset+ypos+1; (int)y < yoffset+ypos+charheight; y += 3) { dc.DrawPoint(xoffset + segoffset, y); } } segoffset += charwidth; segstart = pos+1; } break; case '\t': { if (pos > segstart) { segoffset += DrawText(xoffset, segoffset, yoffset+ypos, segstart, pos); } if (m_sr.ShowHidden(style_id)) { wxColour textcolor = dc.GetTextForeground(); // Buffer text color dc.SetTextForeground(m_theme.invisiblesColor); if(GetTabPoint(segoffset)-segoffset < tabwidth) { const int ntwidth = GetTabPoint(segoffset)-segoffset; dc.DrawBitmap(bmTab.GetSubBitmap(wxRect(tabwidth-ntwidth, 0, ntwidth, charheight)), xoffset + segoffset, yoffset+ypos, false); } else dc.DrawBitmap(bmTab, xoffset + segoffset, yoffset+ypos, false); dc.SetTextForeground(textcolor); // Re-set text color } else if (dc.GetBackgroundMode() != wxTRANSPARENT) { const int ntwidth = GetTabPoint(segoffset)-segoffset; dc.SetPen(dc.GetTextBackground()); dc.SetBrush(wxBrush(dc.GetTextBackground(), wxSOLID)); dc.DrawRectangle(xoffset + segoffset, yoffset+ypos, ntwidth, charheight); } // Indent guides if (isIndent && m_showIndent && segoffset > 0 && IsTabPos(segstart)) { dc.SetPen(m_theme.invisiblesColor); for (unsigned int y = yoffset+ypos+1; (int)y < yoffset+ypos+charheight; y += 3) { dc.DrawPoint(xoffset + segoffset, y); } } segoffset = GetTabPoint(segoffset); segstart = pos+1; } break; case '\n': wxASSERT(textstart + pos == textend-1); if (pos > segstart) { segoffset += DrawText(xoffset, segoffset, yoffset+ypos, segstart, pos); } if (m_sr.ShowHidden(style_id)) { wxColour textcolor = dc.GetTextForeground(); // Buffer text color dc.SetTextForeground(m_theme.invisiblesColor); dc.DrawBitmap(bmNewline, xoffset + segoffset, yoffset+ypos, false); dc.SetTextForeground(textcolor); // Re-set text color //segoffset += charwidth; } // If this is the terminating (last-in-doc) newline and we have // an endstyle, we have to draw the caret on the next (virtual) line if (endstyle && (textstart + pos == m_docLen-1)) { unsigned int style_end = m_sr.GetStyleEnd(next_style_id) - textstart; if (next_style_start == style_end) { // zero length style. Draw a caret. ypos += charheight; // move to next (virtual) line m_sr.ApplyStyle(next_style_id); dc.SetPen(dc.GetTextBackground()); dc.SetBrush(wxBrush(dc.GetTextBackground(), wxSOLID)); dc.DrawRectangle(0, yoffset+ypos, 3, charheight); } } // Check if the background hightlight should be extended if (m_sr.DoExtendBg()) { dc.SetPen(m_sr.GetExtendBgColor()); dc.SetBrush(wxBrush(m_sr.GetExtendBgColor(), wxSOLID)); const unsigned int xpos = xoffset + segoffset; dc.DrawRectangle(xpos, yoffset+ypos, width-xpos, charheight); } //return; // Newline is always last character in line segoffset += m_nlwidth; segstart = pos+1; endstyle = false; // avoid drawing zerolength selection twice break; default: isIndent = false; } } // Draw text after last special char if (segstart < breakpoint) { segoffset += DrawText(xoffset, segoffset, yoffset+ypos, segstart, breakpoint); } // Check if the background hightlight should be extended if (m_sr.DoExtendBgAtPos(textstart + breakpoint)) { dc.SetPen(m_sr.GetExtendBgColor()); dc.SetBrush(wxBrush(m_sr.GetExtendBgColor(), wxSOLID)); const unsigned int xpos = xoffset + segoffset; dc.DrawRectangle(xpos, yoffset+ypos, width-xpos, charheight); } // End-of-line if (i == breakpoints.end()-1) { // If we are at end of text (no newline), we might have to draw a zero-length selection if (endstyle) { unsigned int style_end = m_sr.GetStyleEnd(next_style_id) - textstart; if (next_style_start == style_end) { // zero length style. Draw a caret. m_sr.ApplyStyle(next_style_id); dc.SetPen(dc.GetTextBackground()); dc.SetBrush(wxBrush(dc.GetTextBackground(), wxSOLID)); dc.DrawRectangle(xoffset + segoffset, yoffset+ypos, 3, charheight); } } // Draw fold indicator after last char if (isFolded) { dc.SetTextForeground(m_theme.invisiblesColor); dc.SetTextBackground(m_theme.backgroundColor); const unsigned int foldyoffset = (charheight - m_foldHeight) / 2; // Enabling transparency draws as monochrome dc.DrawBitmap(bmFold, xoffset + segoffset, yoffset+ypos+foldyoffset, false); } } linestart = breakpoint; ypos += charheight; } }
// Build PolyGeo Object from SENC file record PolyTessGeo::PolyTessGeo(unsigned char *polybuf, int nrecl, int index, int senc_file_version) { #define POLY_LINE_HDR_MAX 1000 // Todo Add a try/catch set here, in case SENC file is corrupted?? m_pxgeom = NULL; char hdr_buf[POLY_LINE_HDR_MAX]; int twkb_len; m_buf_head = (char *) polybuf; // buffer beginning m_buf_ptr = m_buf_head; m_nrecl = nrecl; my_bufgets( hdr_buf, POLY_LINE_HDR_MAX ); // Read the s57obj extents as lat/lon sscanf(hdr_buf, " POLYTESSGEOPROP %lf %lf %lf %lf", &xmin, &ymin, &xmax, &ymax); PolyTriGroup *ppg = new PolyTriGroup; ppg->m_bSMSENC = true; ppg->data_type = DATA_TYPE_DOUBLE; int nctr; my_bufgets( hdr_buf, POLY_LINE_HDR_MAX ); sscanf(hdr_buf, "Contours/nWKB %d %d", &nctr, &twkb_len); ppg->nContours = nctr; ppg->pn_vertex = (int *)malloc(nctr * sizeof(int)); int *pctr = ppg->pn_vertex; size_t buf_len = wxMax(twkb_len + 2, 20 + (nctr * 6)); char *buf = (char *)malloc(buf_len); // allocate a buffer guaranteed big enough my_bufgets( buf, buf_len ); // contour nVert, as a char line wxString ivc_str(buf + 10, wxConvUTF8); wxStringTokenizer tkc(ivc_str, wxT(" ,\n")); long icv = 0; while ( tkc.HasMoreTokens() ) { wxString token = tkc.GetNextToken(); if(token.ToLong(&icv)) { if(icv) { *pctr = icv; pctr++; } } } // Read Raw Geometry float *ppolygeo = (float *)malloc(twkb_len + 1); // allow for crlf memcpy(ppolygeo, m_buf_ptr, twkb_len + 1); m_buf_ptr += twkb_len + 1; ppg->pgroup_geom = ppolygeo; TriPrim **p_prev_triprim = &(ppg->tri_prim_head); // Read the PTG_Triangle Geometry in a loop unsigned int tri_type; int nvert; int nvert_max = 0; bool not_finished = true; int total_byte_size = 2 * sizeof(float); while(not_finished) { if((m_buf_ptr - m_buf_head) != m_nrecl) { int *pi = (int *)m_buf_ptr; tri_type = *pi++; nvert = *pi; m_buf_ptr += 2 * sizeof(int); // Here is the usual stop condition, which results from // interpreting the string "POLYEND" as an int if(tri_type == 0x594c4f50) { not_finished = false; break; } TriPrim *tp = new TriPrim; *p_prev_triprim = tp; // make the link p_prev_triprim = &(tp->p_next); tp->p_next = NULL; tp->type = tri_type; tp->nVert = nvert; if(nvert > nvert_max ) // Keep a running tab of largest vertex count nvert_max = nvert; if(senc_file_version > 122){ int byte_size = nvert * 2 * sizeof(float); total_byte_size += byte_size; tp->p_vertex = (double *)m_buf_ptr; m_buf_ptr += byte_size; } else{ int byte_size = nvert * 2 * sizeof(double); total_byte_size += byte_size; tp->p_vertex = (double *)malloc(byte_size); memcpy(tp->p_vertex, m_buf_ptr, byte_size); m_buf_ptr += byte_size; } // Read the triangle primitive bounding box as lat/lon double *pbb = (double *)m_buf_ptr; double abox[4]; memcpy(&abox[0], pbb, 4 * sizeof(double)); tp->tri_box.Set(abox[2], abox[0], abox[3], abox[1]); m_buf_ptr += 4 * sizeof(double); } else // got end of poly not_finished = false; } // while // Convert the vertex arrays into a single float memory allocation to enable efficient access later if(senc_file_version > 122){ unsigned char *vbuf = (unsigned char *)malloc(total_byte_size); TriPrim *p_tp = ppg->tri_prim_head; unsigned char *p_run = vbuf; while( p_tp ) { memcpy(p_run, p_tp->p_vertex, p_tp->nVert * 2 * sizeof(float)); p_tp->p_vertex = (double *)p_run; p_run += p_tp->nVert * 2 * sizeof(float); p_tp = p_tp->p_next; // pick up the next in chain } ppg->bsingle_alloc = true; ppg->single_buffer = vbuf; ppg->single_buffer_size = total_byte_size; ppg->data_type = DATA_TYPE_FLOAT; } m_ppg_head = ppg; m_nvertex_max = nvert_max; free(buf); m_bOK = true; }
void wxGridSelection::UpdateRows( size_t pos, int numRows ) { size_t count = m_cellSelection.GetCount(); size_t n; for ( n = 0; n < count; n++ ) { wxGridCellCoords& coords = m_cellSelection[n]; wxCoord row = coords.GetRow(); if ((size_t)row >= pos) { if (numRows > 0) { // If rows inserted, increase row counter where necessary coords.SetRow(row + numRows); } else if (numRows < 0) { // If rows deleted ... if ((size_t)row >= pos - numRows) { // ...either decrement row counter (if row still exists)... coords.SetRow(row + numRows); } else { // ...or remove the attribute m_cellSelection.RemoveAt(n); n--; count--; } } } } count = m_blockSelectionTopLeft.GetCount(); for ( n = 0; n < count; n++ ) { wxGridCellCoords& coords1 = m_blockSelectionTopLeft[n]; wxGridCellCoords& coords2 = m_blockSelectionBottomRight[n]; wxCoord row1 = coords1.GetRow(); wxCoord row2 = coords2.GetRow(); if ((size_t)row2 >= pos) { if (numRows > 0) { // If rows inserted, increase row counter where necessary coords2.SetRow( row2 + numRows ); if ((size_t)row1 >= pos) coords1.SetRow( row1 + numRows ); } else if (numRows < 0) { // If rows deleted ... if ((size_t)row2 >= pos - numRows) { // ...either decrement row counter (if row still exists)... coords2.SetRow( row2 + numRows ); if ((size_t)row1 >= pos) coords1.SetRow( wxMax(row1 + numRows, (int)pos) ); } else { if ((size_t)row1 >= pos) { // ...or remove the attribute m_blockSelectionTopLeft.RemoveAt(n); m_blockSelectionBottomRight.RemoveAt(n); n--; count--; } else coords2.SetRow( pos ); } } } } count = m_rowSelection.GetCount(); for ( n = 0; n < count; n++ ) { int rowOrCol_ = m_rowSelection[n]; if ((size_t) rowOrCol_ >= pos) { if ( numRows > 0 ) { m_rowSelection[n] += numRows; } else if ( numRows < 0 ) { if ((size_t)rowOrCol_ >= (pos - numRows)) m_rowSelection[n] += numRows; else { m_rowSelection.RemoveAt( n ); n--; count--; } } } } // No need to touch selected columns, unless we removed _all_ // rows, in this case, we remove all columns from the selection. if ( !m_grid->GetNumberRows() ) m_colSelection.Clear(); }
wxCoord ODIconCombo::OnMeasureItem( size_t item ) const { int bmpHeight = bmpArray.Item(item).GetHeight(); return wxMax(itemHeight, bmpHeight); }
void Route::DrawGLRouteLines( ViewPort &vp ) { #ifdef ocpnUSE_GL // Hiliting first // Being special case to draw something for a 1 point route.... ocpnDC dc; if(m_hiliteWidth) { wxColour y = GetGlobalColor( _T ( "YELO1" ) ); wxColour hilt( y.Red(), y.Green(), y.Blue(), 128 ); wxPen HiPen( hilt, m_hiliteWidth, wxPENSTYLE_SOLID ); ocpnDC dc; dc.SetPen( HiPen ); DrawGLLines(vp, &dc); } /* determine color and width */ wxColour col; int width = g_pRouteMan->GetRoutePen()->GetWidth(); //g_route_line_width; if( m_width != wxPENSTYLE_INVALID ) width = m_width; if( m_bRtIsActive ) { col = g_pRouteMan->GetActiveRoutePen()->GetColour(); } else if( m_bRtIsSelected ) { col = g_pRouteMan->GetSelectedRoutePen()->GetColour(); } else { if( m_Colour == wxEmptyString ) { col = g_pRouteMan->GetRoutePen()->GetColour(); } else { for( unsigned int i = 0; i < sizeof( ::GpxxColorNames ) / sizeof(wxString); i++ ) { if( m_Colour == ::GpxxColorNames[i] ) { col = ::GpxxColors[i]; break; } } } } wxPenStyle style = wxPENSTYLE_SOLID; if( m_style != wxPENSTYLE_INVALID ) style = m_style; dc.SetPen( *wxThePenList->FindOrCreatePen( col, width, style ) ); glColor3ub(col.Red(), col.Green(), col.Blue()); glLineWidth( wxMax( g_GLMinSymbolLineWidth, width ) ); dc.SetGLStipple(); DrawGLLines(vp, NULL); glDisable (GL_LINE_STIPPLE); /* direction arrows.. could probably be further optimized for opengl */ wxRoutePointListNode *node = pRoutePointList->GetFirst(); wxPoint rpt1, rpt2; while(node) { RoutePoint *prp = node->GetData(); cc1->GetCanvasPointPix( prp->m_lat, prp->m_lon, &rpt2 ); if(node != pRoutePointList->GetFirst()) RenderSegmentArrowsGL( rpt1.x, rpt1.y, rpt2.x, rpt2.y, vp ); rpt1 = rpt2; node = node->GetNext(); } #endif }
void wxNewBitmapButton::RenderLabelImage( wxBitmap*& destBmp, wxBitmap* srcBmp, bool isEnabled, bool isPressed ) { if ( destBmp != 0 ) return; // render labels on-demand wxMemoryDC srcDc; srcDc.SelectObject( *srcBmp ); bool hasText = ( mTextAlignment != NB_NO_TEXT ) && ( mLabelText.length() != 0 ); bool hasImage = (mTextAlignment != NB_NO_IMAGE); wxSize destDim; wxPoint txtPos; wxPoint imgPos; if ( hasText ) { long txtWidth, txtHeight; srcDc.SetFont( wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) ); srcDc.GetTextExtent( mLabelText, &txtWidth, &txtHeight ); if ( mTextAlignment == NB_ALIGN_TEXT_RIGHT ) { destDim.x = srcBmp->GetWidth() + 2*mTextToLabelGap + txtWidth; destDim.y = wxMax( srcBmp->GetHeight(), txtHeight ); txtPos.x = srcBmp->GetWidth() + mTextToLabelGap; txtPos.y = (destDim.y - txtHeight)/2; imgPos.x = 0; imgPos.y = (destDim.y - srcBmp->GetHeight())/2; } else if ( mTextAlignment == NB_ALIGN_TEXT_BOTTOM ) { destDim.x = wxMax( srcBmp->GetWidth(), txtWidth ); destDim.y = srcBmp->GetHeight() + mTextToLabelGap + txtHeight; txtPos.x = (destDim.x - txtWidth)/2; txtPos.y = srcBmp->GetHeight() + mTextToLabelGap; imgPos.x = (destDim.x - srcBmp->GetWidth())/2; imgPos.y = 0; } else { wxFAIL_MSG(wxT("Unsupported FL alignment type detected in wxNewBitmapButton::RenderLabelImage()")); } } else { imgPos.x = 0; imgPos.y = 0; destDim.x = srcBmp->GetWidth(); destDim.y = srcBmp->GetHeight(); } destBmp = new wxBitmap( int(destDim.x), int(destDim.y) ); wxMemoryDC destDc; destDc.SelectObject( *destBmp ); wxBrush grayBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE), wxSOLID ); destDc.SetBrush( grayBrush ); destDc.SetPen( *wxTRANSPARENT_PEN ); destDc.DrawRectangle( 0,0, destDim.x+1, destDim.y+1 ); if ( isPressed ) { ++imgPos.x; ++imgPos.y; ++txtPos.x; ++txtPos.y; } if ( hasImage ) { destDc.Blit( imgPos.x, imgPos.y, srcBmp->GetWidth(), srcBmp->GetHeight(), &srcDc, 0,0, wxCOPY,true ); } if ( hasText ) { wxWindow* pTopWnd = this; do { wxWindow* pParent = pTopWnd->GetParent(); if ( pParent == 0 ) break; pTopWnd = pParent; } while (1); destDc.SetFont( wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT) ); if ( isEnabled ) { destDc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) ); } else { destDc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW) ); } destDc.SetTextBackground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE) ); destDc.DrawText( mLabelText, txtPos.x, txtPos.y ); } if ( !isEnabled ){ #ifdef __WXMSW__ // This is currently MSW specific gray_out_image_on_dc( destDc, destDim.x, destDim.y ); #else wxBitmap bmp( (const char*)_gDisableImage,8,8); wxBrush checkerBrush(bmp); checkerBrush.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); destDc.SetBrush( checkerBrush ); destDc.DrawRectangle( imgPos.x, imgPos.y, srcBmp->GetWidth()+1, srcBmp->GetHeight()+1); #endif } // adjust button size to fit the new dimensions of the label if ( !mSizeIsSet && 0 ) { mSizeIsSet = true; SetSize( wxDefaultCoord, wxDefaultCoord, destBmp->GetWidth() + mMarginX*2, destBmp->GetHeight() + mMarginY*2, 0 ); } destDc.SelectObject( wxNullBitmap ); #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Map to system colours (void) wxToolBar::MapBitmap(destBmp->GetHBITMAP(), destBmp->GetWidth(), destBmp->GetHeight()); #endif }
static void gtk_collapsiblepane_expanded_callback(GObject * WXUNUSED(object), GParamSpec * WXUNUSED(param_spec), wxCollapsiblePane *p) { // NB: unlike for the "activate" signal, when this callback is called, if // we try to query the "collapsed" status through p->IsCollapsed(), we // get the right value. I.e. here p->IsCollapsed() will return false if // this callback has been called at the end of a collapsed->expanded // transition and viceversa. Inside the "activate" signal callback // p->IsCollapsed() would return the wrong value! wxSize sz; if ( p->IsExpanded() ) { // NB: we cannot use the p->GetBestSize() or p->GetMinSize() functions // here as they would return the size for the collapsed expander // even if the collapsed->expanded transition has already been // completed; we solve this problem doing: sz = p->m_szCollapsed; wxSize panesz = p->GetPane()->GetBestSize(); sz.x = wxMax(sz.x, panesz.x); sz.y += gtk_expander_get_spacing(GTK_EXPANDER(p->m_widget)) + panesz.y; } else // collapsed { // same problem described above: using p->Get[Best|Min]Size() here we // would get the size of the control when it is expanded even if the // expanded->collapsed transition should be complete now... // So, we use the size cached at control-creation time... sz = p->m_szCollapsed; } // VERY IMPORTANT: // just calling // p->OnStateChange(sz); // here would work work BUT: // 1) in the expanded->collapsed transition it provokes a lot of flickering // 2) in the collapsed->expanded transition using the "Change status" wxButton // in samples/collpane application some strange warnings would be generated // by the "clearlooks" theme, if that's your theme. // // So we prefer to use some GTK+ native optimized calls, which prevent too many resize // calculations to happen. Note that the following code has been very carefully designed // and tested - be VERY careful when changing it! // 1) need to update our size hints // NB: this function call won't actually do any long operation // (redraw/relayout/resize) so that it's flicker-free p->SetMinSize(sz); if (p->HasFlag(wxCP_NO_TLW_RESIZE)) { // fire an event wxCollapsiblePaneEvent ev(p, p->GetId(), p->IsCollapsed()); p->HandleWindowEvent(ev); // the user asked to explicitly handle the resizing itself... return; } wxTopLevelWindow * top = wxDynamicCast(wxGetTopLevelParent(p), wxTopLevelWindow); if ( top && top->GetSizer() ) { // 2) recalculate minimal size of the top window sz = top->GetSizer()->CalcMin(); if (top->m_mainWidget) { // 3) MAGIC HACK: if you ever used GtkExpander in a GTK+ program // you know that this magic call is required to make it possible // to shrink the top level window in the expanded->collapsed // transition. This may be sometimes undesired but *is* // necessary and if you look carefully, all GTK+ programs using // GtkExpander perform this trick (e.g. the standard "open file" // dialog of GTK+>=2.4 is not resizable when the expander is // collapsed!) gtk_window_set_resizable (GTK_WINDOW (top->m_widget), p->IsExpanded()); // 4) set size hints top->SetMinClientSize(sz); // 5) set size top->SetClientSize(sz); } } if ( p->m_bIgnoreNextChange ) { // change generated programmatically - do not send an event! p->m_bIgnoreNextChange = false; return; } // fire an event wxCollapsiblePaneEvent ev(p, p->GetId(), p->IsCollapsed()); p->HandleWindowEvent(ev); }
bool StepGuider::UpdateCalibrationState(const PHD_Point& currentLocation) { bool bError = false; try { if (!m_calibrationStartingLocation.IsValid()) { m_calibrationStartingLocation = currentLocation; Debug.AddLine(wxString::Format("Stepguider::UpdateCalibrationstate: starting location = %.2f,%.2f", currentLocation.X, currentLocation.Y)); } wxString status0, status1; int stepsRemainingUp = MaxPosition(UP) - CurrentPosition(UP); int stepsRemainingDown = MaxPosition(DOWN) - CurrentPosition(DOWN); int stepsRemainingRight = MaxPosition(RIGHT) - CurrentPosition(RIGHT); int stepsRemainingLeft = MaxPosition(LEFT) - CurrentPosition(LEFT); stepsRemainingUp /= m_calibrationStepsPerIteration; stepsRemainingDown /= m_calibrationStepsPerIteration; stepsRemainingRight /= m_calibrationStepsPerIteration; stepsRemainingLeft /= m_calibrationStepsPerIteration; int stepsRemainingDownAndRight = wxMax(stepsRemainingDown, stepsRemainingRight); assert(stepsRemainingUp >= 0); assert(stepsRemainingDown >= 0); assert(stepsRemainingRight >= 0); assert(stepsRemainingLeft >= 0); assert(stepsRemainingDownAndRight >= 0); bool moveUp = false; bool moveDown = false; bool moveRight = false; bool moveLeft = false; double x_dist; double y_dist; switch (m_calibrationState) { case CALIBRATION_STATE_GOTO_LOWER_RIGHT_CORNER: if (stepsRemainingDownAndRight > 0) { status0.Printf(_("Init Calibration: %3d"), stepsRemainingDownAndRight); moveDown = stepsRemainingDown > 0; moveRight = stepsRemainingRight > 0; break; } Debug.AddLine(wxString::Format("Falling through to state AVERAGE_STARTING_LOCATION, position=(%.2f, %.2f)", currentLocation.X, currentLocation.Y)); m_calibrationAverageSamples = 0; m_calibrationAveragedLocation.SetXY(0.0, 0.0); m_calibrationState = CALIBRATION_STATE_AVERAGE_STARTING_LOCATION; // fall through case CALIBRATION_STATE_AVERAGE_STARTING_LOCATION: m_calibrationAverageSamples++; m_calibrationAveragedLocation += currentLocation; status0.Printf(_("Averaging: %3d"), m_samplesToAverage - m_calibrationAverageSamples + 1); if (m_calibrationAverageSamples < m_samplesToAverage ) { break; } m_calibrationAveragedLocation /= m_calibrationAverageSamples; m_calibrationStartingLocation = m_calibrationAveragedLocation; m_calibrationIterations = 0; Debug.AddLine(wxString::Format("Falling through to state GO_LEFT, startinglocation=(%.2f, %.2f)", m_calibrationStartingLocation.X, m_calibrationStartingLocation.Y)); m_calibrationState = CALIBRATION_STATE_GO_LEFT; // fall through case CALIBRATION_STATE_GO_LEFT: if (stepsRemainingLeft > 0) { status0.Printf(_("Left Calibration: %3d"), stepsRemainingLeft); m_calibrationIterations++; moveLeft = true; x_dist = m_calibrationStartingLocation.dX(currentLocation); y_dist = m_calibrationStartingLocation.dY(currentLocation); GuideLog.CalibrationStep(this, "Left", stepsRemainingLeft, x_dist, y_dist, currentLocation, m_calibrationStartingLocation.Distance(currentLocation)); m_calibrationDetails.raSteps.push_back(wxRealPoint(x_dist, y_dist)); // Just put "left" in "ra" steps break; } Debug.AddLine(wxString::Format("Falling through to state AVERAGE_CENTER_LOCATION, position=(%.2f, %.2f)", currentLocation.X, currentLocation.Y)); m_calibrationAverageSamples = 0; m_calibrationAveragedLocation.SetXY(0.0, 0.0); m_calibrationState = CALIBRATION_STATE_AVERAGE_CENTER_LOCATION; // fall through case CALIBRATION_STATE_AVERAGE_CENTER_LOCATION: m_calibrationAverageSamples++; m_calibrationAveragedLocation += currentLocation; status0.Printf(_("Averaging: %3d"), m_samplesToAverage -m_calibrationAverageSamples+1); if (m_calibrationAverageSamples < m_samplesToAverage ) { break; } m_calibrationAveragedLocation /= m_calibrationAverageSamples; m_calibration.xAngle = m_calibrationStartingLocation.Angle(m_calibrationAveragedLocation); m_calibration.xRate = m_calibrationStartingLocation.Distance(m_calibrationAveragedLocation) / (m_calibrationIterations * m_calibrationStepsPerIteration); status1.Printf(_("angle=%.1f rate=%.2f"), m_calibration.xAngle * 180. / M_PI, m_calibration.xRate); GuideLog.CalibrationDirectComplete(this, "Left", m_calibration.xAngle, m_calibration.xRate); Debug.AddLine(wxString::Format("LEFT calibration completes with angle=%.1f rate=%.2f", m_calibration.xAngle * 180. / M_PI, m_calibration.xRate)); Debug.AddLine(wxString::Format("distance=%.2f iterations=%d", m_calibrationStartingLocation.Distance(m_calibrationAveragedLocation), m_calibrationIterations)); m_calibrationStartingLocation = m_calibrationAveragedLocation; m_calibrationIterations = 0; m_calibrationState = CALIBRATION_STATE_GO_UP; Debug.AddLine(wxString::Format("Falling through to state GO_UP, startinglocation=(%.2f, %.2f)", m_calibrationStartingLocation.X, m_calibrationStartingLocation.Y)); // fall through case CALIBRATION_STATE_GO_UP: if (stepsRemainingUp > 0) { status0.Printf(_("up Calibration: %3d"), stepsRemainingUp); m_calibrationIterations++; moveUp = true; x_dist = m_calibrationStartingLocation.dX(currentLocation); y_dist = m_calibrationStartingLocation.dY(currentLocation); GuideLog.CalibrationStep(this, "Up", stepsRemainingLeft, x_dist, y_dist, currentLocation, m_calibrationStartingLocation.Distance(currentLocation)); m_calibrationDetails.decSteps.push_back(wxRealPoint(x_dist, y_dist)); // Just put "up" in "dec" steps break; } Debug.AddLine(wxString::Format("Falling through to state AVERAGE_ENDING_LOCATION, position=(%.2f, %.2f)", currentLocation.X, currentLocation.Y)); m_calibrationAverageSamples = 0; m_calibrationAveragedLocation.SetXY(0.0, 0.0); m_calibrationState = CALIBRATION_STATE_AVERAGE_ENDING_LOCATION; // fall through case CALIBRATION_STATE_AVERAGE_ENDING_LOCATION: m_calibrationAverageSamples++; m_calibrationAveragedLocation += currentLocation; status0.Printf(_("Averaging: %3d"), m_samplesToAverage -m_calibrationAverageSamples+1); if (m_calibrationAverageSamples < m_samplesToAverage ) { break; } m_calibrationAveragedLocation /= m_calibrationAverageSamples; m_calibration.yAngle = m_calibrationAveragedLocation.Angle(m_calibrationStartingLocation); m_calibration.yRate = m_calibrationStartingLocation.Distance(m_calibrationAveragedLocation) / (m_calibrationIterations * m_calibrationStepsPerIteration); status1.Printf(_("angle=%.1f rate=%.2f"), m_calibration.yAngle * 180. / M_PI, m_calibration.yRate); GuideLog.CalibrationDirectComplete(this, "Up", m_calibration.yAngle, m_calibration.yRate); Debug.AddLine(wxString::Format("UP calibration completes with angle=%.1f rate=%.2f", m_calibration.yAngle * 180. / M_PI, m_calibration.yRate)); Debug.AddLine(wxString::Format("distance=%.2f iterations=%d", m_calibrationStartingLocation.Distance(m_calibrationAveragedLocation), m_calibrationIterations)); m_calibrationStartingLocation = m_calibrationAveragedLocation; m_calibrationState = CALIBRATION_STATE_RECENTER; Debug.AddLine(wxString::Format("Falling through to state RECENTER, position=(%.2f, %.2f)", currentLocation.X, currentLocation.Y)); // fall through case CALIBRATION_STATE_RECENTER: status0.Printf(_("Finish Calibration: %3d"), stepsRemainingDownAndRight/2); moveRight = (CurrentPosition(LEFT) >= m_calibrationStepsPerIteration); moveDown = (CurrentPosition(UP) >= m_calibrationStepsPerIteration); if (moveRight || moveDown) { Debug.AddLine(wxString::Format("CurrentPosition(LEFT)=%d CurrentPosition(UP)=%d", CurrentPosition(LEFT), CurrentPosition(UP))); break; } m_calibrationState = CALIBRATION_STATE_COMPLETE; Debug.AddLine(wxString::Format("Falling through to state COMPLETE, position=(%.2f, %.2f)", currentLocation.X, currentLocation.Y)); // fall through case CALIBRATION_STATE_COMPLETE: m_calibration.declination = 0.; m_calibration.pierSide = PIER_SIDE_UNKNOWN; m_calibration.rotatorAngle = Rotator::RotatorPosition(); SetCalibration(m_calibration); SetCalibrationDetails(m_calibrationDetails, m_calibration.xAngle, m_calibration.yAngle); status1 = _T("calibration complete"); GuideLog.CalibrationComplete(this); Debug.AddLine("Calibration Complete"); break; default: assert(false); break; } if (moveUp) { assert(!moveDown); pFrame->ScheduleCalibrationMove(this, UP, m_calibrationStepsPerIteration); } if (moveDown) { assert(!moveUp); pFrame->ScheduleCalibrationMove(this, DOWN, m_calibrationStepsPerIteration); } if (moveRight) { assert(!moveLeft); pFrame->ScheduleCalibrationMove(this, RIGHT, m_calibrationStepsPerIteration); } if (moveLeft) { assert(!moveRight); pFrame->ScheduleCalibrationMove(this, LEFT, m_calibrationStepsPerIteration); } if (m_calibrationState != CALIBRATION_STATE_COMPLETE) { if (status1.IsEmpty()) { double dX = m_calibrationStartingLocation.dX(currentLocation); double dY = m_calibrationStartingLocation.dY(currentLocation); double dist = m_calibrationStartingLocation.Distance(currentLocation); status1.Printf(_T("dx=%4.1f dy=%4.1f dist=%4.1f"), dX, dY, dist); } } if (!status0.IsEmpty()) { pFrame->SetStatusText(status0, 0); } if (!status1.IsEmpty()) { pFrame->SetStatusText(status1, 1); } } catch (wxString Msg) { POSSIBLY_UNUSED(Msg); bError = true; ClearCalibration(); } return bError; }
bool EffectTruncSilence::Process() { SelectedTrackListOfKindIterator iter(Track::Wave, mTracks); WaveTrack *t; double t0 = mT0; double t1 = mT1; int tndx; int tcount = 0; int fr; // Init using first track t = (WaveTrack *) iter.First(); double rate = t->GetRate(); sampleCount blockLen = t->GetMaxBlockSize(); // Get the left and right bounds for all tracks while (t) { // Make sure all tracks have the same sample rate if (rate != t->GetRate()) { wxMessageBox(_("All tracks must have the same sample rate"), _("Truncate Silence")); return false; } // Count the tracks tcount++; // Set the current bounds to whichever left marker is // greater and whichever right marker is less t0 = wxMax(mT0, t->GetStartTime()); t1 = wxMin(mT1, t->GetEndTime()); // Use the smallest block size of all the tracks blockLen = wxMin(blockLen, t->GetMaxBlockSize()); // Iterate to the next track t = (WaveTrack*) iter.Next(); } // Just a sanity check, really it should be much higher if(blockLen < 4*mBlendFrameCount) blockLen = 4*mBlendFrameCount; // Transform the marker timepoints to samples t = (WaveTrack *) iter.First(); sampleCount start = t->TimeToLongSamples(t0); sampleCount end = t->TimeToLongSamples(t1); // Bigger buffers reduce 'reset' //blockLen *= 8; // Stress-test the logic for cutting samples through block endpoints //blockLen /= 8; // Set thresholds // We have a lower bound on the amount of silence we chop out at a time // to avoid chopping up low frequency sounds. We're good down to 10Hz // if we use 100ms. const float minTruncMs = 1.0f; double truncDbSilenceThreshold = Enums::Db2Signal[mTruncDbChoiceIndex]; int truncInitialAllowedSilentSamples = int((wxMax( mTruncInitialAllowedSilentMs, minTruncMs) * rate) / 1000.0); int truncLongestAllowedSilentSamples = int((wxMax( mTruncLongestAllowedSilentMs, minTruncMs) * rate) / 1000.0); // Require at least 4 samples for lengths if(truncInitialAllowedSilentSamples < 4) truncInitialAllowedSilentSamples = 4; if(truncLongestAllowedSilentSamples < 4) truncLongestAllowedSilentSamples = 4; // If the cross-fade is longer than the minimum length, // then limit the cross-fade length to the minimum length // This allows us to have reasonable cross-fade by default // and still allow for 1ms minimum lengths if(truncInitialAllowedSilentSamples < mBlendFrameCount) mBlendFrameCount = truncInitialAllowedSilentSamples; if(truncLongestAllowedSilentSamples < mBlendFrameCount) mBlendFrameCount = truncLongestAllowedSilentSamples; // For sake of efficiency, don't let blockLen be less than double the longest silent samples // up until a sane limit of 1Meg samples while((blockLen > 0) && (blockLen < truncLongestAllowedSilentSamples*2) && (blockLen < 1048576)) { blockLen *= 2; } // Don't allow either value to be more than half of the block length if(truncLongestAllowedSilentSamples > blockLen/2) truncLongestAllowedSilentSamples = blockLen/2; if(truncInitialAllowedSilentSamples > truncLongestAllowedSilentSamples) truncInitialAllowedSilentSamples = truncLongestAllowedSilentSamples; // We use the 'longest' variable as additive to the 'initial' variable truncLongestAllowedSilentSamples -= truncInitialAllowedSilentSamples; // Perform the crossfade half-way through the minimum removed silence duration int rampInFrames = (truncInitialAllowedSilentSamples + mBlendFrameCount) / 2; if(rampInFrames > truncInitialAllowedSilentSamples) rampInFrames = truncInitialAllowedSilentSamples; // Allocate buffers float **buffer = new float*[tcount]; for (tndx = 0; tndx < tcount; tndx++) { buffer[tndx] = new float[blockLen]; } // Start processing //Track::All is needed because this effect has clear functionality this->CopyInputTracks(Track::All); // Set up mOutputTracks. SelectedTrackListOfKindIterator iterOut(Track::Wave, mOutputTracks); sampleCount index = start; sampleCount outTrackOffset = start; bool cancelled = false; // Reset bool ignoringFrames = false; bool truncToMinimum = true; // Ignore the initial samples until we get above the noise floor sampleCount consecutiveSilentFrames = 0; sampleCount truncIndex = 0; sampleCount i = 0; sampleCount keep; while (index < end) { // Limit size of current block if we've reached the end sampleCount count = blockLen-i; if ((index + count) > end) { count = end - index; } // Fill the buffers tndx = 0; t = (WaveTrack *) iter.First(); while (t) { t->Get((samplePtr)(buffer[tndx++]+i), floatSample, index, count); t = (WaveTrack *) iter.Next(); } // Shift over to account for samples remaining from prior block sampleCount limit = count+i; // Look for silences in current block for ( ; i < limit; i++) { // Is current frame in all tracks below threshold bool below = true; for (tndx = 0; tndx < tcount; tndx++) { if (fabs(buffer[tndx][i]) >= truncDbSilenceThreshold) { below = false; break; } } // Make sure we cross-fade and output the last silence // so we get a smooth transition into whatever follows the selected region // Also set the 'truncToMinimum' flag so that the last silence is truncated to the minimum amount if(below && ((index+i+1) == end)) { below = false; truncToMinimum = true; } // Count frame if it's below threshold if (below) { consecutiveSilentFrames++; // Ignore this frame (equivalent to cutting it) // otherwise, keep sample to be part of allowed silence if (consecutiveSilentFrames > truncInitialAllowedSilentSamples) { ignoringFrames = true; continue; } } else { if (ignoringFrames == true) { // Scale the consectiveSilentFrames so we keep a silence duration // which is proportional to the original silence up to the limit keep = consecutiveSilentFrames - truncInitialAllowedSilentSamples; keep /= mSilenceCompressRatio; // The first and last samples always get truncated to the minimum amount if(truncToMinimum == true) keep = 0; if(keep > truncLongestAllowedSilentSamples) keep = truncLongestAllowedSilentSamples; if(keep < 0) keep = 0; // Compute the location of the cross-fade to be halfway through the silence // with restriction to the samples we still have available to use rampInFrames = (truncInitialAllowedSilentSamples - keep + mBlendFrameCount) / 2; if(rampInFrames > truncInitialAllowedSilentSamples) rampInFrames = truncInitialAllowedSilentSamples; if(rampInFrames < mBlendFrameCount) rampInFrames = mBlendFrameCount; // Include the cross-fade samples in the count to make the loop logic easier keep += rampInFrames; truncIndex -= rampInFrames; // back up for cross-fade sampleCount curOffset = i - keep; if(curOffset < 0) { // This should never happen, but just in case... keep += curOffset - rampInFrames; if(keep < mBlendFrameCount) keep = mBlendFrameCount; curOffset = 0; } if(truncIndex < 0) { // This should never happen, but just in case... truncIndex = 0; } for (tndx = 0; tndx < tcount; tndx++) { // Cross fade the cut point for (fr = 0; fr < mBlendFrameCount; fr++) { buffer[tndx][truncIndex+fr] = ((mBlendFrameCount-fr)*buffer[tndx][truncIndex+fr] + fr*buffer[tndx][curOffset + fr]) / mBlendFrameCount; } // Append the 'keep' samples, if any for ( ; fr < keep; fr++) { buffer[tndx][truncIndex+fr] = buffer[tndx][curOffset + fr]; } } truncIndex += keep; } consecutiveSilentFrames = 0; ignoringFrames = false; truncToMinimum = false; } // Can get here either because > dbThreshold // or silence duration isn't longer than allowed for (tndx = 0; tndx < tcount; tndx++) { buffer[tndx][truncIndex] = buffer[tndx][i]; } truncIndex++; } // Update tracks if any samples were removed, now or before if (outTrackOffset + truncIndex != index + limit) { // Put updated sample back into output tracks. tndx = 0; t = (WaveTrack *) iterOut.First(); while (t) { t->Set((samplePtr)buffer[tndx++], floatSample, outTrackOffset, truncIndex); t = (WaveTrack *) iterOut.Next(); } } // If currently in a silent section, retain samples for the next pass if(ignoringFrames) { keep = consecutiveSilentFrames - truncInitialAllowedSilentSamples; if(keep > (truncLongestAllowedSilentSamples+mBlendFrameCount)) keep = truncLongestAllowedSilentSamples+mBlendFrameCount; for (tndx = 0; tndx < tcount; tndx++) { for(fr = 0; fr < truncInitialAllowedSilentSamples; fr++) { buffer[tndx][fr] = buffer[tndx][truncIndex-truncInitialAllowedSilentSamples+fr]; } for(fr = 0; fr < keep; fr++) { buffer[tndx][truncInitialAllowedSilentSamples+fr] = buffer[tndx][i-keep+fr]; } } // Update the output index, less what we are retaining for next time outTrackOffset += truncIndex - truncInitialAllowedSilentSamples; // Append the following buffer to the existing data i = consecutiveSilentFrames = truncInitialAllowedSilentSamples + keep; truncIndex = truncInitialAllowedSilentSamples; } else { // Maintain output index outTrackOffset += truncIndex; // Reset the buffer pointers to the beginning i = 0; truncIndex = 0; consecutiveSilentFrames = 0; } // Update progress and bail if user cancelled cancelled = TrackProgress(0, ((double)index / (double)end)); if (cancelled) { break; } // Bump to next block index += count; } AudacityProject *p = GetActiveProject(); if (!p) return false; // Remove stale data at end of output tracks. if (!cancelled && (outTrackOffset < end)) { t = (WaveTrack *) iterOut.First(); if( p->IsSticky() ) t->Clear(outTrackOffset / rate, t1, mOutputTracks); else while(t) { t->Clear(outTrackOffset / rate, t1, mOutputTracks); t = (WaveTrack *) iterOut.Next(); } t1 = outTrackOffset / rate; } // Free buffers for (tndx = 0; tndx < tcount; tndx++) { delete [] buffer[tndx]; } delete [] buffer; mT0 = t0; mT1 = t1; this->ReplaceProcessedTracks(!cancelled); return !cancelled; }
void TexFont::Build( wxFont &font, bool blur ) { /* avoid rebuilding if the parameters are the same */ if(font == m_font && blur == m_blur) return; m_font = font; m_blur = blur; m_maxglyphw = 0; m_maxglyphh = 0; wxScreenDC sdc; sdc.SetFont( font ); for( int i = MIN_GLYPH; i < MAX_GLYPH; i++ ) { wxCoord gw, gh; wxString text; if(i == DEGREE_GLYPH) text = wxString::Format(_T("%c"), 0x00B0); //_T("°"); else text = wxString::Format(_T("%c"), i); wxCoord descent, exlead; sdc.GetTextExtent( text, &gw, &gh, &descent, &exlead, &font ); // measure the text tgi[i].width = gw; tgi[i].height = gh; tgi[i].advance = gw; m_maxglyphw = wxMax(tgi[i].width, m_maxglyphw); m_maxglyphh = wxMax(tgi[i].height, m_maxglyphh); } /* add extra pixel to give a border between rows of characters without this, in some cases a faint line can be see on the edge from the character above */ m_maxglyphh++; int w = COLS_GLYPHS * m_maxglyphw; int h = ROWS_GLYPHS * m_maxglyphh; wxASSERT(w < 2048 && h < 2048); /* make power of 2 */ for(tex_w = 1; tex_w < w; tex_w *= 2); for(tex_h = 1; tex_h < h; tex_h *= 2); wxBitmap tbmp(tex_w, tex_h); wxMemoryDC dc; dc.SelectObject(tbmp); dc.SetFont( font ); /* fill bitmap with black */ dc.SetBackground( wxBrush( wxColour( 0, 0, 0 ) ) ); dc.Clear(); /* draw the text white */ dc.SetTextForeground( wxColour( 255, 255, 255 ) ); /* wxPen pen(wxColour( 255, 255, 255 )); wxBrush brush(wxColour( 255, 255, 255 ), wxTRANSPARENT); dc.SetPen(pen); dc.SetBrush(brush); */ int row = 0, col = 0; for( int i = MIN_GLYPH; i < MAX_GLYPH; i++ ) { if(col == COLS_GLYPHS) { col = 0; row++; } tgi[i].x = col * m_maxglyphw; tgi[i].y = row * m_maxglyphh; wxString text; if(i == DEGREE_GLYPH) text = wxString::Format(_T("%c"), 0x00B0); //_T("°"); else text = wxString::Format(_T("%c"), i); dc.DrawText(text, tgi[i].x, tgi[i].y ); // dc.DrawRectangle(tgi[i].x, tgi[i].y, tgi[i].advance, tgi[i].height); col++; } dc.SelectObject(wxNullBitmap); wxImage image = tbmp.ConvertToImage(); GLuint format, internalformat; int stride; format = GL_ALPHA; internalformat = format; stride = 1; if( m_blur ) image = image.Blur(1); unsigned char *imgdata = image.GetData(); if(imgdata){ unsigned char *teximage = (unsigned char *) malloc( stride * tex_w * tex_h ); for( int j = 0; j < tex_w*tex_h; j++ ) for( int k = 0; k < stride; k++ ) teximage[j * stride + k] = imgdata[3*j]; Delete(); glGenTextures( 1, &texobj ); glBindTexture( GL_TEXTURE_2D, texobj ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST/*GL_LINEAR*/ ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, internalformat, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, teximage ); free(teximage); } m_built = true; }
OCPNRegion ViewPort::GetVPRegionIntersect( const OCPNRegion &Region, size_t nPoints, float *llpoints, int chart_native_scale, wxPoint *ppoints ) { // Calculate the intersection between a given OCPNRegion (Region) and a polygon specified by lat/lon points. // If the viewpoint is highly overzoomed wrt to chart native scale, the polygon region may be huge. // This can be very expensive, and lead to crashes on some platforms (gtk in particular) // So, look for this case and handle appropriately with respect to the given Region if( chart_scale < chart_native_scale / 10 ) { // Make a positive definite vp ViewPort vp_positive = *this; while( vp_positive.vpBBox.GetMinX() < 0 ) { vp_positive.clon += 360.; wxPoint2DDouble t( 360., 0. ); vp_positive.vpBBox.Translate( t ); } // Scan the points one-by-one, so that we can get min/max to make a bbox float *pfp = llpoints; float lon_max = -10000.; float lon_min = 10000.; float lat_max = -10000.; float lat_min = 10000.; for( unsigned int ip = 0; ip < nPoints; ip++ ) { lon_max = wxMax(lon_max, pfp[1]); lon_min = wxMin(lon_min, pfp[1]); lat_max = wxMax(lat_max, pfp[0]); lat_min = wxMin(lat_min, pfp[0]); pfp += 2; } wxBoundingBox chart_box( lon_min, lat_min, lon_max, lat_max ); // Case: vpBBox is completely outside the chart box, or vice versa // Return an empty region if( chart_box.IntersectOut( (wxBoundingBox&) vp_positive.vpBBox ) ) { if( chart_box.IntersectOut( (wxBoundingBox&) vpBBox ) ) { // try again with the chart translated 360 wxPoint2DDouble rtw( 360., 0. ); wxBoundingBox trans_box = chart_box; trans_box.Translate( rtw ); if( trans_box.IntersectOut( (wxBoundingBox&) vp_positive.vpBBox ) ) { if( trans_box.IntersectOut( (wxBoundingBox&) vpBBox ) ) { return OCPNRegion(); } } } } // Case: vpBBox is completely inside the chart box // Note that this test is not perfect, and will fail for some charts. // The chart coverage may be essentially triangular, and the viewport box // may be in the "cut off" segment of the chart_box, and not actually // exhibit any true overlap. Results will be reported incorrectly. // How to fix: maybe scrub the chart points and see if it is likely that // a region may be safely built and intersection tested. if( _IN == chart_box.Intersect( (wxBoundingBox&) vp_positive.vpBBox ) ) { return Region; } if(_IN == chart_box.Intersect((wxBoundingBox&)vpBBox)) { return Region; } // The ViewPort and the chart region overlap in some way.... // Create the intersection of the two bboxes // Boxes must be same phase while( chart_box.GetMinX() < 0 ) { wxPoint2DDouble t( 360., 0. ); chart_box.Translate( t ); } double cb_minlon = wxMax(chart_box.GetMinX(), vp_positive.vpBBox.GetMinX()); double cb_maxlon = wxMin(chart_box.GetMaxX(), vp_positive.vpBBox.GetMaxX()); double cb_minlat = wxMax(chart_box.GetMinY(), vp_positive.vpBBox.GetMinY()); double cb_maxlat = wxMin(chart_box.GetMaxY(), vp_positive.vpBBox.GetMaxY()); if( cb_maxlon < cb_minlon ) cb_maxlon += 360.; wxPoint p1 = GetPixFromLL( cb_maxlat, cb_minlon ); // upper left wxPoint p2 = GetPixFromLL( cb_minlat, cb_maxlon ); // lower right OCPNRegion r( p1, p2 ); r.Intersect( Region ); return r; } // More "normal" case wxPoint *pp; // Use the passed point buffer if available if( ppoints == NULL ) pp = new wxPoint[nPoints]; else pp = ppoints; float *pfp = llpoints; wxPoint p = GetPixFromLL( pfp[0], pfp[1] ); int poly_x_max, poly_y_max, poly_x_min, poly_y_min; bool valid = false; for( unsigned int ip = 0; ip < nPoints; ip++ ) { wxPoint p = GetPixFromLL( pfp[0], pfp[1] ); pp[ip] = p; if(p.x == INVALID_COORD) continue; if(valid) { poly_x_max = wxMax(poly_x_max, p.x); poly_y_max = wxMax(poly_y_max, p.y); poly_x_min = wxMin(poly_x_min, p.x); poly_y_min = wxMin(poly_y_min, p.y); } else { poly_x_max = p.x; poly_y_max = p.y; poly_x_min = p.x; poly_y_min = p.y; valid = true; } pfp += 2; } if(!valid) { delete[] pp; return OCPNRegion(); //empty; } // We want to avoid processing regions with very large rectangle counts, // so make some tests for special cases float_2Dpt p0, p1, p2, p3; // First, calculate whether any segment of the input polygon intersects the specified Region int nrect = 0; bool b_intersect = false; OCPNRegionIterator screen_region_it1( Region ); while( screen_region_it1.HaveRects() ) { wxRect rect = screen_region_it1.GetRect(); double lat, lon; // The screen region corners GetLLFromPix( wxPoint(rect.x, rect.y), &lat, &lon ); p0.y = lat; p0.x = lon; GetLLFromPix( wxPoint(rect.x + rect.width, rect.y), &lat, &lon ); p1.y = lat; p1.x = lon; GetLLFromPix( wxPoint(rect.x + rect.width, rect.y + rect.height), &lat, &lon ); p2.y = lat; p2.x = lon; GetLLFromPix( wxPoint(rect.x, rect.y + rect.height), &lat, &lon ); p3.y = lat; p3.x = lon; for(size_t i=0 ; i < nPoints-1 ; i++){ // Quick check on y dimension int y0 = pp[i].y; int y1 = pp[i+1].y; if(y0 == INVALID_COORD || y1 == INVALID_COORD) continue; if( ((y0 < rect.y) && (y1 < rect.y)) || ((y0 > rect.y+rect.height) && (y1 > rect.y+rect.height)) ) continue; // both ends of line outside of box, top or bottom // Look harder float_2Dpt f0; f0.y = llpoints[i * 2]; f0.x = llpoints[(i * 2) + 1]; float_2Dpt f1; f1.y = llpoints[(i+1) * 2]; f1.x = llpoints[((i+1) * 2) + 1]; b_intersect |= Intersect_FL( p0, p1, f0, f1) != 0; if(b_intersect) break; b_intersect |= Intersect_FL( p1, p2, f0, f1) != 0; if(b_intersect) break; b_intersect |= Intersect_FL( p2, p3, f0, f1) != 0; if(b_intersect) break; b_intersect |= Intersect_FL( p3, p0, f0, f1) != 0; if(b_intersect) break; // Must check the case where the input polygon has been pre-normalized, eg (0 < lon < 360), as cm93 f0.x -= 360.; f1.x -= 360.; b_intersect |= Intersect_FL( p0, p1, f0, f1) != 0; if(b_intersect) break; b_intersect |= Intersect_FL( p1, p2, f0, f1) != 0; if(b_intersect) break; b_intersect |= Intersect_FL( p2, p3, f0, f1) != 0; if(b_intersect) break; b_intersect |= Intersect_FL( p3, p0, f0, f1) != 0; if(b_intersect) break; } // Check segment, last point back to first point if(!b_intersect){ float_2Dpt f0; f0.y = llpoints[(nPoints-1) * 2]; f0.x = llpoints[((nPoints-1) * 2) + 1]; float_2Dpt f1; f1.y = llpoints[0]; f1.x = llpoints[1]; b_intersect |= Intersect_FL( p0, p1, f0, f1) != 0; b_intersect |= Intersect_FL( p1, p2, f0, f1) != 0; b_intersect |= Intersect_FL( p2, p3, f0, f1) != 0; b_intersect |= Intersect_FL( p3, p0, f0, f1) != 0; f0.x -= 360.; f1.x -= 360.; b_intersect |= Intersect_FL( p0, p1, f0, f1) != 0; b_intersect |= Intersect_FL( p1, p2, f0, f1) != 0; b_intersect |= Intersect_FL( p2, p3, f0, f1) != 0; b_intersect |= Intersect_FL( p3, p0, f0, f1) != 0; } screen_region_it1.NextRect(); nrect++; } // If there is no itersection, we need to consider the case where // the subject polygon is entirely within the Region bool b_contained = false; if(!b_intersect){ OCPNRegionIterator screen_region_it2( Region ); while( screen_region_it2.HaveRects() ) { wxRect rect = screen_region_it2.GetRect(); for(size_t i=0 ; i < nPoints-1 ; i++){ int x0 = pp[i].x; int y0 = pp[i].y; if(x0 == INVALID_COORD) continue; if((x0 < rect.x) || (x0 > rect.x+rect.width)) continue; if((y0 < rect.y) || (y0 > rect.y+rect.height)) continue; b_contained = true; break; } screen_region_it2.NextRect(); } } #if 1 // and here is the payoff if(!b_contained && !b_intersect){ // Two cases to consider wxRect rpoly( poly_x_min, poly_y_min, poly_x_max - poly_x_min , poly_y_max - poly_y_min); wxRect rRegion = Region.GetBox(); if(rpoly.Contains(rRegion)){ // subject poygon may be large enough to fully encompass the target Region, // but it might not, especially for irregular or concave charts. // So we cannot directly shortcut here // Better check.... #if 1 if(nrect == 1){ // most common case // If the subject polygon contains the center of the target rectangle, then // the intersection must be the target rectangle float rlat = (p0.y + p2.y)/2.; float rlon = (p0.x + p1.x)/2.; if(G_PtInPolygon_FL((float_2Dpt *)llpoints, nPoints, rlon, rlat)){ if( NULL == ppoints ) delete[] pp; return Region; } rlon += 360.; if(G_PtInPolygon_FL((float_2Dpt *)llpoints, nPoints, rlon, rlat)){ if( NULL == ppoints ) delete[] pp; return Region; } // otherwise, there is no intersection else{ if( NULL == ppoints ) delete[] pp; wxRegion r; return r; } } #endif } else{ // Subject polygon is entirely outside of target Region // so the intersection must be empty. if( NULL == ppoints ) delete[] pp; wxRegion r; return r; } } else if(b_contained && !b_intersect){ // subject polygon is entirely withing the target Region, // so the intersection is the subject polygon OCPNRegion r = OCPNRegion( nPoints, pp ); if( NULL == ppoints ) delete[] pp; return r; } #endif #ifdef __WXGTK__ sigaction(SIGSEGV, NULL, &sa_all_old); // save existing action for this signal struct sigaction temp; sigaction(SIGSEGV, NULL, &temp);// inspect existing action for this signal temp.sa_handler = catch_signals;// point to my handler sigemptyset(&temp.sa_mask);// make the blocking set // empty, so that all // other signals will be // unblocked during my handler temp.sa_flags = 0; sigaction(SIGSEGV, &temp, NULL); if(sigsetjmp(env, 1))// Something in the below code block faulted.... { sigaction(SIGSEGV, &sa_all_old, NULL); // reset signal handler return Region; } else { OCPNRegion r = OCPNRegion(nPoints, pp); if(NULL == ppoints) delete[] pp; sigaction(SIGSEGV, &sa_all_old, NULL); // reset signal handler r.Intersect(Region); return r; } #else OCPNRegion r = OCPNRegion( nPoints, pp ); if( NULL == ppoints ) delete[] pp; r.Intersect( Region ); return r; #endif }