#pragma once #include #include namespace zdg_ui2 { using namespace System; //using namespace System::ComponentModel; using namespace System::Resources; using namespace System::Windows::Forms; using namespace System::Drawing; using namespace System::Drawing::Imaging; using namespace System::Threading; using namespace ZedGraph; //using namespace System::Runtime::InteropServices; //[DllImport("gdi32.dll")] ////extern IntPtr CopyEnhMetaFileA(IntPtr hemfSrc, System::Text::StringBuilder* hNULL); //extern IntPtr CopyEnhMetaFileA(IntPtr hemfSrc, String^ hNULL); // Form1 is only used with MULTICHART public ref class ChartObj : public System::Object { public: ChartObject* chartobject_ptr; public: ChartObj(ChartObject* ptr) { this->chartobject_ptr = ptr; } }; public ref class Form1 : public System::Windows::Forms::Form { public: long int tickStart; public: Form1(ChartObject *ptr) { this->chartobject_ptr = ptr; if (Phreeqc* ptr = this->chartobject_ptr->Get_phreeqc()) { ptr->Get_chart_handler().Increment_active_charts(); } InitializeComponent(); col_use = 0; symbol_use = 0; Y2 = false; phreeqc_done = false; Y2show = false; background = true; hints = true; grid = true; } static void ThreadForm(Object^ data) { ChartObject *ptr = ((ChartObj^)(data))->chartobject_ptr; Form1 ^myForm = gcnew Form1(ptr); myForm->ShowDialog(); myForm->~Form1(); } private: bool phreeqc_done; private: void SetSize() { zg1->Location = Point( 0, 0 ); // Leave a small margin around the outside of the control zg1->Size = System::Drawing::Size( ClientRectangle.Width - 0, ClientRectangle.Height - 0 ); } System::Void MyFormClosingEventHandler( System::Object^ sender, System::Windows::Forms::FormClosingEventArgs ^e) { ChartObject *chart = this->chartobject_ptr; if (chart != NULL) { chart->Set_done(true); System::Threading::Interlocked::Exchange(this->chartobject_ptr->usingResource, 0); if (Phreeqc* ptr = chart->Get_phreeqc()) { ptr->Get_chart_handler().Decrement_active_charts(); //chart->Set_phreeqc(NULL); } } this->chartobject_ptr = NULL; } System::Void Form1_Load(System::Object ^sender, System::EventArgs ^e) { CreateGraph( zg1 ); SetSize(); } System::Void Form1_Resize(System::Object ^sender, System::EventArgs ^e) { SetSize(); } //static bool LogX, LogY, LogY2; bool LogX, LogY, LogY2; private: bool check_neg_log( int i, int i2) { ChartObject *chart = this->chartobject_ptr; if (chart == NULL) return false; std::vector &Curves = chart->Get_Curves(); if (LogX && chart->Get_axis_scale_x()[4] == 10.0 && Curves[i]->Get_x()[i2] <= 0) { if (Phreeqc* ptr = chart->Get_phreeqc()) { ptr->warning_msg("Obtained x_value <= 0, removing point..."); } //axis_scale_x[4] = NA; /* if reverting to linear... */ //LogX = false; return true; } if (Curves[i]->Get_y()[i2] <= 0 && (chart->Get_axis_scale_y()[4] == 10.0 || chart->Get_axis_scale_y2()[4] == 10.0)) { if (Curves[i]->Get_y_axis() == 2 && LogY2) { if (Phreeqc* ptr = chart->Get_phreeqc()) { ptr->warning_msg("Obtained sy_value <= 0, removing point......"); } //axis_scale_y2[4] = NA; //LogY2 = false; return true; } else if (LogY) { if (Phreeqc* ptr = chart->Get_phreeqc()) { ptr->warning_msg("Obtained y_value <= 0, removing point......"); } //axis_scale_y[4] = NA; //LogY = false; return true; } } return false; } private: PointPairList ^list; int col_use, symbol_use; bool Y2, Y2show; // static cli::array ^ColorList = {"Red", "Green", "Blue", "Orange", "Magenta", "Yellow", "Black", "Cyan", "Brown", "Lime", "Gray" }; static cli::array ^ColorList = {"Red", "Green", "Blue", "Orange", "Magenta", "Black", "Cyan", "Brown", "Lime", "Gray" }; bool background, hints, grid; ZedGraph::GraphObjList ^GOL_no_hints; ZedGraph::GraphObjList ^GOL_hints; void DefineCurves(GraphPane ^myPane, int init) { ChartObject *chart = this->chartobject_ptr; if (chart == NULL) { return; } std::vector Curves; size_t i; for (i = 0; i < chart->Get_CurvesCSV().size(); i++) { Curves.push_back(chart->Get_CurvesCSV()[i]); } for (i = 0; i < chart->Get_Curves().size(); i++) { Curves.push_back(chart->Get_Curves()[i]); } chart->Set_curve_added(false); // Set the titles and axis labels myPane->Title->Text = gcnew String(chart->Get_chart_title().c_str()); if (chart->Get_axis_titles().size() > 0) myPane->XAxis->Title->Text = gcnew String(chart->Get_axis_titles()[0].c_str()); if (chart->Get_axis_titles().size() > 1) myPane->YAxis->Title->Text = gcnew String(chart->Get_axis_titles()[1].c_str()); if (chart->Get_axis_titles().size() > 2) myPane->Y2Axis->Title->Text = gcnew String(chart->Get_axis_titles()[2].c_str()); LineItem ^myCurve; Color col; String ^s_t; if (chart->Get_axis_scale_x()[4] == 10.0) LogX = true; else LogX = false; if (chart->Get_axis_scale_y()[4] == 10.0) LogY = true; else LogY = false; if (chart->Get_axis_scale_y2()[4] == 10.0) LogY2 = true; else LogY2 = false; //Rewrite all curves zg1->GraphPane->CurveList->Clear(); for (size_t i = 0; i < Curves.size(); i++) { // even curves with no data //if (Curves[i]->Get_x().size() == 0) continue; list = gcnew PointPairList(); if (Curves[i]->Get_y_axis() == 2) { Y2 = true; Y2show = true; } else Y2 = false; for (int i2 = 0; (i2 < (int) Curves[i]->Get_x().size()); i2++) { if ((LogX && Curves[i]->Get_x()[i2] <=0) || (LogY && !Y2 && Curves[i]->Get_y()[i2] <=0) || (LogY2 && Y2 && Curves[i]->Get_y()[i2] <=0)) continue; else list->Add( Curves[i]->Get_x()[i2], Curves[i]->Get_y()[i2] ); } col = Color::FromName(gcnew String(Curves[i]->Get_color().c_str())); if (!col.IsKnownColor) { col = Color::FromName(ColorList[col_use]); std::string newcol; ToString(col.ToString(), newcol); Utilities::replace("Color [","",newcol); Utilities::replace("]","",newcol); Curves[i]->Set_color(newcol); } if (++col_use > 6) col_use = 0; SymbolType symb = chart->Return_SymbolType (Curves[i]->Get_symbol()); // id s_t = gcnew String(Curves[i]->Get_id().c_str()); // Add curve to chart myCurve = myPane->AddCurve( s_t, list, col, symb ); // Curve with no points is invisible if (Curves[i]->Get_x().size() == 0) { myCurve->IsVisible = false; myCurve->Label->IsVisible = false; } if (Curves[i]->Get_line_w() > 0.0) myCurve->Line->Width = (float) Curves[i]->Get_line_w(); else myCurve->Line->IsVisible = false; /* hmm... dash/dot don`t display well */ // myCurve->Line->Style = System::Drawing::Drawing2D::DashStyle::Dot; myCurve->Symbol->Fill = gcnew Fill( Color::FromName("White") ); if (Curves[i]->Get_symbol_size() > 0.0) myCurve->Symbol->Size = (float) Curves[i]->Get_symbol_size(); else myCurve->Symbol->IsVisible = false; myCurve->Symbol->Border->Width = (float) Curves[i]->Get_line_w(); if (Y2) myCurve->IsY2Axis = true; delete list; } if (Y2show) myPane->Legend->Position = ZedGraph::LegendPos::TopCenter; else myPane->Legend->Position = ZedGraph::LegendPos::Right; myPane->Legend->FontSpec->Size = 12; myPane->Legend->FontSpec->IsBold = false; // Show the x axis grid myPane->XAxis->MajorGrid->IsVisible = true; if (fabs(chart->Get_axis_scale_x()[0] - NA) > 1e-3) myPane->XAxis->Scale->Min = chart->Get_axis_scale_x()[0]; else myPane->XAxis->Scale->MinAuto = true; if (fabs(chart->Get_axis_scale_x()[1] - NA) > 1e-3) myPane->XAxis->Scale->Max = chart->Get_axis_scale_x()[1]; else myPane->XAxis->Scale->MaxAuto = true; if (fabs(chart->Get_axis_scale_x()[2] - NA) > 1e-3) myPane->XAxis->Scale->MajorStep = chart->Get_axis_scale_x()[2]; else myPane->XAxis->Scale->MajorStepAuto = true; if (fabs(chart->Get_axis_scale_x()[3] - NA) > 1e-3) { myPane->XAxis->Scale->MinorStep = chart->Get_axis_scale_x()[3]; if (chart->Get_axis_scale_x()[3] == 0.0) // remove minor tics myPane->XAxis->MinorTic->Size = 0; } else myPane->XAxis->Scale->MinorStepAuto = true; if (chart->Get_axis_scale_x()[4] == 10.0) myPane->XAxis->Type = AxisType::Log; // Make the Y axis scale red // myPane->YAxis->Scale->FontSpec->FontColor = Color::Red; // myPane->YAxis->Title->FontSpec->FontColor = Color::Red; // turn off the opposite tics so the Y tics don`t show up on the Y2 axis if (Y2show) { myPane->YAxis->MajorTic->IsOpposite = false; myPane->YAxis->MinorTic->IsOpposite = false; } // Don`t display the Y zero line myPane->YAxis->MajorGrid->IsZeroLine = false; // Align the Y axis labels so they are flush to the axis myPane->YAxis->Scale->Align = AlignP::Inside; myPane->YAxis->MajorGrid->IsVisible = true; if (fabs(chart->Get_axis_scale_y()[0] - NA) > 1e-3) myPane->YAxis->Scale->Min = chart->Get_axis_scale_y()[0]; else myPane->YAxis->Scale->MinAuto = true; if (fabs(chart->Get_axis_scale_y()[1] - NA) > 1e-3) myPane->YAxis->Scale->Max = chart->Get_axis_scale_y()[1]; else myPane->YAxis->Scale->MaxAuto = true; if (fabs(chart->Get_axis_scale_y()[2] - NA) > 1e-3) myPane->YAxis->Scale->MajorStep = chart->Get_axis_scale_y()[2]; else myPane->YAxis->Scale->MajorStepAuto = true; if (fabs(chart->Get_axis_scale_y()[3] - NA) > 1e-3) { myPane->YAxis->Scale->MinorStep = chart->Get_axis_scale_y()[3]; if (chart->Get_axis_scale_y()[3] == 0.0) // remove minor tics myPane->YAxis->MinorTic->Size = 0; } else myPane->YAxis->Scale->MinorStepAuto = true; if (chart->Get_axis_scale_y()[4] == 10.0) myPane->YAxis->Type = AxisType::Log; // Enable the Y2 axis display if (Y2show) { myPane->Y2Axis->IsVisible = true; // Make the Y2 axis scale blue // myPane->Y2Axis->Scale->FontSpec->FontColor = Color::Blue; // myPane->Y2Axis->Title->FontSpec->FontColor = Color::Blue; // turn off the opposite tics so the Y2 tics don`t show up on the Y axis myPane->Y2Axis->MajorTic->IsOpposite = false; myPane->Y2Axis->MinorTic->IsOpposite = false; // Don`t display the Y2 axis grid lines myPane->Y2Axis->MajorGrid->IsVisible = false; // Align the Y2 axis labels so they are flush to the axis myPane->Y2Axis->Scale->Align = AlignP::Inside; if (fabs(chart->Get_axis_scale_y2()[0] - NA) > 1e-3) myPane->Y2Axis->Scale->Min = chart->Get_axis_scale_y2()[0]; else myPane->Y2Axis->Scale->MinAuto = true; if (fabs(chart->Get_axis_scale_y2()[1] - NA) > 1e-3) myPane->Y2Axis->Scale->Max = chart->Get_axis_scale_y2()[1]; else myPane->Y2Axis->Scale->MaxAuto = true; if (fabs(chart->Get_axis_scale_y2()[2] - NA) > 1e-3) myPane->Y2Axis->Scale->MajorStep = chart->Get_axis_scale_y2()[2]; else myPane->Y2Axis->Scale->MajorStepAuto = true; if (fabs(chart->Get_axis_scale_y2()[3] - NA) > 1e-3) { myPane->Y2Axis->Scale->MinorStep = chart->Get_axis_scale_y2()[3]; if (chart->Get_axis_scale_y2()[3] == 0.0) // remove minor tics myPane->Y2Axis->MinorTic->Size = 0; } else myPane->Y2Axis->Scale->MinorStepAuto = true; if (chart->Get_axis_scale_y2()[4] == 10.0) myPane->Y2Axis->Type = AxisType::Log; } myPane->XAxis->MinorTic->IsOutside = false; myPane->XAxis->MajorTic->IsOutside = false; myPane->YAxis->MinorTic->IsOutside = false; myPane->YAxis->MajorTic->IsOutside = false; myPane->Y2Axis->MinorTic->IsOutside = false; myPane->Y2Axis->MajorTic->IsOutside = false; // Fill the axis background with a gradient //myPane->Chart->Fill = gcnew Fill( Color::White, Color::LightYellow, 45.0f ); /* FromArgb(255, 255, 224) */ if (this->background) { myPane->Chart->Fill = gcnew Fill( Color::White, Color::FromArgb(255, 255, 230), 45.0f ); } else { myPane->Chart->Fill = gcnew Fill( Color::White, Color::White, 45.0f ); } if (this->grid) { myPane->XAxis->MajorGrid->IsVisible = true; myPane->YAxis->MajorGrid->IsVisible = true; } else { myPane->XAxis->MajorGrid->IsVisible = false; myPane->YAxis->MajorGrid->IsVisible = false; } // normalize pane size... myPane->BaseDimension = 8.0F; // increase bottom margin to accommodate text options... myPane->Margin->Bottom = 15.0F; // Make sure auto scale, Refresh zg1->AxisChange(); zg1->Refresh(); } public: void CreateGraph( ZedGraphControl ^z1 ) { // Get a reference to the GraphPane instance in the ZedGraphControl GraphPane ^myPane = z1->GraphPane; // lock thread while (0 != System::Threading::Interlocked::CompareExchange(this->chartobject_ptr->usingResource, 2, 0)) { System::Threading::Thread::Sleep(5); } try { DefineCurves(myPane, 0); // Add text boxes with instructions... GOL_no_hints = gcnew ZedGraph::GraphObjList(myPane->GraphObjList); TextObj ^text; text = gcnew TextObj( L" Click right mouse for options... \0", 0.01f, 0.99f, CoordType::PaneFraction, AlignH::Left, AlignV::Bottom ); text->FontSpec->StringAlignment = StringAlignment::Near; text->FontSpec->Size = 10; text->FontSpec->FontColor = Color::Red; text->ZOrder = ZOrder::H_BehindAll; myPane->GraphObjList->Add( text ); text = gcnew TextObj( L" Press Alt + F4 to quit", 0.81f, 0.99f, CoordType::PaneFraction, AlignH::Left, AlignV::Bottom ); text->FontSpec->StringAlignment = StringAlignment::Near; text->FontSpec->Size = 10; text->FontSpec->FontColor = Color::Red; text->ZOrder = ZOrder::H_BehindAll; myPane->GraphObjList->Add( text ); GOL_hints = gcnew ZedGraph::GraphObjList(myPane->GraphObjList); if (this->hints) { myPane->GraphObjList = GOL_hints; } else { myPane->GraphObjList = GOL_no_hints; } // Enable scrollbars if needed... /*z1->IsShowHScrollBar = true; z1->IsShowVScrollBar = true; z1->IsAutoScrollRange = true; z1->IsScrollY2 = true;*/ // OPTIONAL: Show tooltips when the mouse hovers over a point z1->IsShowPointValues = false; z1->PointValueEvent += gcnew ZedGraphControl::PointValueHandler( this, &Form1::MyPointValueHandler ); // OPTIONAL: Add a custom context menu item z1->ContextMenuBuilder += gcnew ZedGraphControl::ContextMenuBuilderEventHandler( this, &Form1::MyContextMenuBuilder ); // OPTIONAL: Handle the Zoom Event z1->ZoomEvent += gcnew ZedGraphControl::ZoomEventHandler( this, &Form1::MyZoomEvent ); // Size the control to fit the window SetSize(); // Tell ZedGraph to calculate the axis ranges // Note that you MUST call this after enabling IsAutoScrollRange, since AxisChange() sets // up the proper scrolling parameters z1->AxisChange(); // Make sure the Graph gets redrawn z1->Invalidate(); timer1->Interval = this->chartobject_ptr->Get_update_time_chart(); timer1->Enabled = true; timer1->Start(); tickStart = Environment::TickCount; } catch (...) { //unlock thread int n = System::Threading::Interlocked::Exchange(this->chartobject_ptr->usingResource, 0); assert(n == 2); throw; } //unlock thread int n = System::Threading::Interlocked::Exchange(this->chartobject_ptr->usingResource, 0); assert(n == 2); } /// /// Display customized tooltips when the mouse hovers over a point /// System::String ^MyPointValueHandler( ZedGraphControl ^control, GraphPane ^pane, CurveItem ^curve, int iPt ) { // Get the PointPair that is under the mouse PointPair pt = curve[iPt]; return curve->Label->Text + " is " + pt.Y.ToString( "e3" ) + " units at X = " + pt.X.ToString( "e3" ); } // Add some explanation to the menu.. void MyContextMenuBuilder( ZedGraphControl ^control, System::Windows::Forms::ContextMenuStrip ^menuStrip, Point mousePt, ZedGraphControl::ContextMenuObjectState objState ) { // removes Copy menuStrip->Items->RemoveAt(0); // removes Save Image As menuStrip->Items->RemoveAt(0); ToolStripMenuItem ^item = gcnew ToolStripMenuItem(); item->Text = L"Zoom: left mouse + drag\nPan: middle mouse + drag"; menuStrip->Items->Insert(5, item ); ToolStripMenuItem ^item3 = gcnew ToolStripMenuItem(); item3->Text = L"Chart options..."; item3->Click += gcnew System::EventHandler(this, &zdg_ui2::Form1::SetChartOptions ); menuStrip->Items->Insert(0, item3 ); //ToolStripMenuItem ^item5 = gcnew ToolStripMenuItem(); //item5->Text = L"Toggle Hints"; //item5->Click += gcnew System::EventHandler(this, &zdg_ui2::Form1::ToggleHints ); //menuStrip->Items->Insert(0, item5 ); ToolStripMenuItem ^item2 = gcnew ToolStripMenuItem(); item2->Text = L"Save Data to File..."; item2->Click += gcnew System::EventHandler(this, &zdg_ui2::Form1::SaveCurves ); menuStrip->Items->Insert(0, item2 ); ToolStripMenuItem ^item4 = gcnew ToolStripMenuItem(); item4->Text = L"Save Image As..."; item4->Click += gcnew System::EventHandler(this, &zdg_ui2::Form1::SaveImage ); menuStrip->Items->Insert(0, item4 ); } void form_error_msg( std::string estring ) { if (this->chartobject_ptr != NULL) { if (Phreeqc* ptr = this->chartobject_ptr->Get_phreeqc()) { ptr->error_msg(estring.c_str(), CONTINUE); } } else { std::cerr << "ERROR: " << estring << std::endl; } } void SaveCurves( System::Object ^sender, System::EventArgs ^e ) { SaveFileDialog^ saveFileDialog1 = gcnew SaveFileDialog; //TCHAR dir[MAX_PATH]; //::GetCurrentDirectory(MAX_PATH, dir); //String ^d = gcnew String(dir); //saveFileDialog1->InitialDirectory = d; saveFileDialog1->FileName = "curves.u_g"; saveFileDialog1->Filter = "User graph files (*.u_g)|*.u_g|txt files (*.txt)|*.txt|All files (*.*)|*.*"; saveFileDialog1->FilterIndex = 1; saveFileDialog1->RestoreDirectory = true; #undef OK if ( saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK ) { std::string file_name; ToString(saveFileDialog1->FileName, file_name); std::ofstream f_out(file_name.c_str(), std::ifstream::out); if (!f_out.is_open()) { std::ostringstream estream; estream << "Could not open file to save curves for USER_GRAPH " << file_name; form_error_msg(estream.str()); return; } // write headings size_t max_points = 0; f_out.precision(4); for (int i = 0; i < zg1->GraphPane->CurveList->Count; i++) { LineItem ^curve; curve = (LineItem ^) zg1->GraphPane->CurveList[i]; // Get the PointPairList IPointListEdit ^ip = (IPointListEdit^) curve->Points; // Calculate max_points if ((size_t) ip->Count > max_points) max_points = ip->Count; // write headers std::string s_std; ToString(curve->Label->Text, s_std); f_out.width(12); f_out << "x" << "\t"; f_out.width(12); if (s_std.size() > 0) { f_out << s_std << "\t"; } else { f_out << "y" << "\t"; } } f_out << std::endl; // write data size_t i2 = 0; f_out << std::scientific; f_out.precision(4); while (i2 < max_points) { for (int i = 0; i < zg1->GraphPane->CurveList->Count; i++) { LineItem ^curve; curve = (LineItem ^) zg1->GraphPane->CurveList[i]; // Get the PointPairList IPointListEdit ^ip = (IPointListEdit^) curve->Points; if (i2 < (size_t) ip->Count) { //double x = ip[i]->X; f_out.width(12); f_out << ip[(int) i2]->X << "\t"; f_out.width(12); f_out << ip[(int) i2]->Y << "\t"; } else if (i2 < max_points) { f_out.width(13); f_out << "\t"; f_out.width(13); f_out << "\t"; } } f_out << std::endl; i2++; } f_out.close(); } else { // no dialog std::ostringstream estream; estream << "Could not open dialog to save curves. "; form_error_msg(estream.str()); return; } return; } // Respond to a Zoom Event void MyZoomEvent( ZedGraphControl ^control, ZoomState ^oldState, ZoomState ^newState ) { // Here we get notification everytime the user zooms } void SetChartOptions( System::Object ^sender, System::EventArgs ^e ) { // Create form Form ^graphOptions = gcnew Form; graphOptions->Text = "Chart options"; graphOptions->ShowIcon = false; graphOptions->BringToFront(); graphOptions->MinimumSize = System::Drawing::Size(255, 230); graphOptions->MaximumSize = System::Drawing::Size(255, 230); graphOptions->Size = System::Drawing::Size(255, 230); graphOptions->StartPosition = System::Windows::Forms::FormStartPosition::CenterParent; // Check box for hints CheckBox ^cb1 = gcnew CheckBox; cb1->Appearance = Appearance::Normal; cb1->ThreeState = false; cb1->AutoCheck = true; cb1->Location = System::Drawing::Point(5, 10); if (this->hints) { cb1->CheckState = CheckState::Checked; } else { cb1->CheckState = CheckState::Unchecked; } cb1->Text = "Show hints"; cb1->Visible = true; graphOptions->Controls->Add(cb1); // Check box for background color CheckBox ^cb2 = gcnew CheckBox; cb2->Appearance = Appearance::Normal; cb2->ThreeState = false; cb2->AutoCheck = true; cb2->Location = System::Drawing::Point(5, 60); if (this->background) { cb2->CheckState = CheckState::Checked; } else { cb2->CheckState = CheckState::Unchecked; } cb2->Text = "Show colored background"; cb2->AutoSize = true; cb2->Visible = true; graphOptions->Controls->Add(cb2); // checkbox for grid CheckBox ^cb3 = gcnew CheckBox; cb3->Appearance = Appearance::Normal; cb3->ThreeState = false; cb3->AutoCheck = true; cb3->Location = System::Drawing::Point(5, 110); if (this->grid) { cb3->CheckState = CheckState::Checked; } else { cb3->CheckState = CheckState::Unchecked; } cb3->Text = "Show grid lines"; cb3->Visible = true; graphOptions->Controls->Add(cb3); // done button for Form Button^ button1 = gcnew Button; button1->DialogResult = System::Windows::Forms::DialogResult::OK; button1->Text = "Done"; button1->Location = System::Drawing::Point(75, 160); graphOptions->Controls->Add(button1); graphOptions->AcceptButton = button1; // cancel button for Form Button^ button2 = gcnew Button; button2->DialogResult = System::Windows::Forms::DialogResult::Cancel; button2->Text = "Cancel"; button2->Location = System::Drawing::Point(155, 160); graphOptions->Controls->Add(button2); graphOptions->CancelButton = button2; if (graphOptions->ShowDialog() == System::Windows::Forms::DialogResult::OK) { this->hints = (cb1->CheckState == CheckState::Checked); this->background = (cb2->CheckState == CheckState::Checked); this->grid = (cb3->CheckState == CheckState::Checked); } if (this->background) { zg1->GraphPane->Chart->Fill = gcnew Fill( Color::White, Color::FromArgb(255, 255, 230), 45.0f ); } else { zg1->GraphPane->Chart->Fill = gcnew Fill( Color::White, Color::White, 45.0f ); } if (this->grid) { zg1->GraphPane->XAxis->MajorGrid->IsVisible = true; zg1->GraphPane->YAxis->MajorGrid->IsVisible = true; } else { zg1->GraphPane->XAxis->MajorGrid->IsVisible = false; zg1->GraphPane->YAxis->MajorGrid->IsVisible = false; } if (this->hints) { zg1->GraphPane->GraphObjList = GOL_hints; } else { zg1->GraphPane->GraphObjList = GOL_no_hints; } zg1->Refresh(); } void SaveImage( System::Object ^sender, System::EventArgs ^e ) { ZedGraph::GraphObjList ^copy = gcnew ZedGraph::GraphObjList(zg1->GraphPane->GraphObjList); zg1->GraphPane->GraphObjList = GOL_no_hints; zg1->SaveAs(); zg1->GraphPane->GraphObjList = copy; } void BatchSaveImage( ) { ChartObject *chart = this->chartobject_ptr; assert(chart->Get_batch() > 0); // Save GraphObjList ZedGraph::GraphObjList ^GOL_copy = gcnew ZedGraph::GraphObjList(zg1->GraphPane->GraphObjList); // Don`t write red hint boxes zg1->GraphPane->GraphObjList = GOL_no_hints; // Set background if (chart->Get_batch_background()) { zg1->GraphPane->Chart->Fill = gcnew Fill( Color::White, Color::FromArgb(255, 255, 230), 45.0f ); } else { zg1->GraphPane->Chart->Fill = gcnew Fill( Color::White, Color::White, 45.0f ); } // Set grid if (chart->Get_batch_grid()) { zg1->GraphPane->XAxis->MajorGrid->IsVisible = true; zg1->GraphPane->YAxis->MajorGrid->IsVisible = true; } else { zg1->GraphPane->XAxis->MajorGrid->IsVisible = false; zg1->GraphPane->YAxis->MajorGrid->IsVisible = false; } // Save the graph if (this->zg1) { ImageFormat ^format = ImageFormat::Png; switch (chart->Get_batch()) { case 2: format = ImageFormat::Png; break; case 3: format = ImageFormat::Gif; break; case 4: format = ImageFormat::Jpeg; break; case 5: format = ImageFormat::Tiff; break; case 6: format = ImageFormat::Bmp; break; default: break; } switch (chart->Get_batch()) { case 1: // emf { System::String ^fn = gcnew System::String(chart->Get_batch_fn().c_str()); System::Drawing::Imaging::Metafile ^metaFile = this->zg1->MasterPane->GetMetafile(); metaFile->Save(fn); } break; case 2: // bitmaps case 3: case 4: case 5: case 6: { System::String ^fn = gcnew System::String(chart->Get_batch_fn().c_str()); System::IO::FileStream ^myStream = gcnew System::IO::FileStream(fn, System::IO::FileMode::Create); zg1->MasterPane->GetImage()->Save( myStream, format); myStream->Close(); } default: break; } } } private: void timer1_Tick(System::Object ^sender, System::EventArgs ^e ) { LineItem ^curve; ChartObject *chart = this->chartobject_ptr; if (chart == NULL) return; //lock for thread while (0 != System::Threading::Interlocked::CompareExchange(chart->usingResource, 3, 0)) { System::Threading::Thread::Sleep(5); } try { if (this->chartobject_ptr->Get_curve_added()) { DefineCurves(zg1->GraphPane, zg1->GraphPane->CurveList->Count); } else if (this->chartobject_ptr->Get_point_added()) { // Make list of curves std::vector Curves; size_t j; for (j = 0; j < chart->Get_CurvesCSV().size(); j++) { Curves.push_back(chart->Get_CurvesCSV()[j]); } for (j = 0; j < chart->Get_Curves().size(); j++) { Curves.push_back(chart->Get_Curves()[j]); } // Add points to curves ... for (int i = 0; i < zg1->GraphPane->CurveList->Count; i++) { curve = (LineItem ^) zg1->GraphPane->CurveList[i]; // Get the PointPairList IPointListEdit ^ip = (IPointListEdit^) curve->Points; if ((size_t) ip->Count < Curves[i]->Get_x().size()) { if (Curves[i]->Get_y_axis() == 2) Y2 = true; else Y2 = false; for ( size_t i2 = ip->Count; i2 < Curves[i]->Get_x().size(); i2++ ) { if ((LogX && Curves[i]->Get_x()[i2] <=0) || (LogY && !Y2 && Curves[i]->Get_y()[i2] <=0) || (LogY2 && Y2 && Curves[i]->Get_y()[i2] <=0)) continue; else ip->Add(Curves[i]->Get_x()[i2], Curves[i]->Get_y()[i2] ); } } } // Add points to curves ... //size_t i, k; //k = 0; //for (i = 0; i < Curves.size(); i++) //{ // if (Curves[i]->Get_x().size() == 0) continue; // curve = (LineItem ^) zg1->GraphPane->CurveList[k++]; // // Get the PointPairList // IPointListEdit ^ip = (IPointListEdit^) curve->Points; // if ((size_t) ip->Count < Curves[i]->Get_x().size()) // { // if (Curves[i]->Get_y_axis() == 2) // Y2 = true; // else // Y2 = false; // for ( size_t i2 = ip->Count; i2 < Curves[i]->Get_x().size(); i2++ ) // { // if ((LogX && Curves[i]->Get_x()[i2] <=0) // || (LogY && !Y2 && Curves[i]->Get_y()[i2] <=0) // || (LogY2 && Y2 && Curves[i]->Get_y()[i2] <=0)) // continue; // else // ip->Add(Curves[i]->Get_x()[i2], Curves[i]->Get_y()[i2] ); // } // } //} /* explicitly reset the max in case of log scale, zedgraphs doesn`t do this... */ if ((fabs(chart->Get_axis_scale_x()[1] - NA) < 1e-3) && zg1->GraphPane->XAxis->Type == AxisType::Log) { double max = -1e99; for (int i = 0; i < zg1->GraphPane->CurveList->Count; i++) { if (Curves[i]->Get_x().size() > 0) { if (Curves[i]->Get_x()[Curves[i]->Get_x().size() - 1] > max) max = Curves[i]->Get_x()[Curves[i]->Get_x().size() - 1]; } } if (max > 0) { max += pow(10.0, log10(max / 3)); } else { zg1->GraphPane->XAxis->Scale->Min = 0; max = zg1->GraphPane->XAxis->Scale->Min + 1.0; } zg1->GraphPane->XAxis->Scale->Max = max; } if ((fabs(chart->Get_axis_scale_y()[1] - NA) < 1e-3) && zg1->GraphPane->YAxis->Type == AxisType::Log) { double max = -1e99; for (int i = 0; i < zg1->GraphPane->CurveList->Count; i++) { curve = (LineItem^)zg1->GraphPane->CurveList[i]; if (curve->IsY2Axis) continue; if (Curves[i]->Get_y().size() > 0) { if (Curves[i]->Get_y()[Curves[i]->Get_y().size() - 1] > max) max = Curves[i]->Get_y()[Curves[i]->Get_y().size() - 1]; } } if (max > 0) { max += pow(10.0, log10(max / 3)); } else { zg1->GraphPane->YAxis->Scale->Min = 0; max = zg1->GraphPane->YAxis->Scale->Min + 1.0; } zg1->GraphPane->YAxis->Scale->Max = max; } if ((fabs(chart->Get_axis_scale_y2()[1] - NA) < 1e-3) && zg1->GraphPane->Y2Axis->Type == AxisType::Log) { double max = -1e99; for (int i = 0; i < zg1->GraphPane->CurveList->Count; i++) { curve = (LineItem^)zg1->GraphPane->CurveList[i]; if (!curve->IsY2Axis) continue; if (Curves[i]->Get_y().size() > 0) { if (Curves[i]->Get_y()[Curves[i]->Get_y().size() - 1] > max) max = Curves[i]->Get_y()[Curves[i]->Get_y().size() - 1]; } } if (max > 0.0) { max += pow(10.0, log10(max / 3)); } else { zg1->GraphPane->Y2Axis->Scale->Min = 0; max = zg1->GraphPane->Y2Axis->Scale->Min + 1.0; } zg1->GraphPane->Y2Axis->Scale->Max = max; } zg1->AxisChange(); zg1->Refresh(); } // // Following asserts may not be true for Log scales // negative values are rejected, so chart may have fewer points than phreeqc // //for (size_t j = 0; j < chart->Get_CurvesCSV().size(); j++) //{ // if (zg1->GraphPane->CurveList[j]->Points->Count != chart->Get_CurvesCSV()[j]->Get_x().size()) // { // fprintf(stderr, "graph points = %d\n", zg1->GraphPane->CurveList[j]->Points->Count); // fprintf(stderr, "phreeqc points = %d\n", chart->Get_CurvesCSV()[j]->Get_x().size()); // } // assert(zg1->GraphPane->CurveList[j]->Points->Count == chart->Get_CurvesCSV()[j]->Get_x().size()); //} //for (int j = chart->Get_CurvesCSV().size(); j < zg1->GraphPane->CurveList->Count; j++) //{ // int k = j - chart->Get_CurvesCSV().size(); // if (zg1->GraphPane->CurveList[j]->Points->Count != chart->Get_Curves()[k]->Get_x().size()) // { // fprintf(stderr, "%d %d graph points = %d\n", j, k, zg1->GraphPane->CurveList[j]->Points->Count); // fprintf(stderr, "phreeqc points = %d\n", chart->Get_Curves()[k]->Get_x().size()); // } // assert(zg1->GraphPane->CurveList[j]->Points->Count == chart->Get_Curves()[k]->Get_x().size()); //} chart->Set_point_added(false); if (chart->Get_end_timer()) { timer1->Stop(); chart->Set_done(true); phreeqc_done = true; int batch = chart->Get_batch(); if (batch > 0) { BatchSaveImage(); } //unlock thread before setting chartobject_ptr to NULL int n = System::Threading::Interlocked::Exchange(this->chartobject_ptr->usingResource, 0); assert(n == 3); //this->phreeqc_ptr = NULL; this->chartobject_ptr = NULL; if (batch >= 0) { this->Close(); } return; } } catch(...) { int n = System::Threading::Interlocked::Exchange(this->chartobject_ptr->usingResource, 0); assert(n == 3); throw; } //unlock thread int n = System::Threading::Interlocked::Exchange(this->chartobject_ptr->usingResource, 0); assert(n == 3); //tickStart = Environment::TickCount; return; } void ToString(System::String^ src, std::string& dest) { using namespace System::Runtime::InteropServices; const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(src)).ToPointer(); dest = chars; Marshal::FreeHGlobal(IntPtr((void*)chars)); } ~Form1() { if (this->zg1) delete zg1; //if (this->timer1) delete timer1); if (components) { delete components; } } public: ZedGraph::ZedGraphControl ^zg1; private: System::Windows::Forms::Timer ^timer1; private: System::ComponentModel::Container ^components; ChartObject * chartobject_ptr; public: #pragma region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// void InitializeComponent() { //System::Threading::Thread::Sleep(5000); this->components = (gcnew System::ComponentModel::Container()); this->zg1 = (gcnew ZedGraph::ZedGraphControl()); this->timer1 = (gcnew System::Windows::Forms::Timer( this->components )); this->SuspendLayout(); // // zg1 // this->zg1->Location = System::Drawing::Point(12, 12); this->zg1->Name = L"zg1"; this->zg1->ScrollGrace = 0; this->zg1->ScrollMaxX = 0; this->zg1->ScrollMaxY = 0; this->zg1->ScrollMaxY2 = 0; this->zg1->ScrollMinX = 0; this->zg1->ScrollMinY = 0; this->zg1->ScrollMinY2 = 0; this->zg1->Size = System::Drawing::Size(this->chartobject_ptr->Get_PanelWidth() - 2 * 12, chartobject_ptr->Get_PanelHeight() - 2 * 12); this->zg1->TabIndex = 0; this->timer1->Tick += gcnew System::EventHandler( this, &Form1::timer1_Tick ); // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->AutoValidate = System::Windows::Forms::AutoValidate::EnablePreventFocusChange; this->ClientSize = System::Drawing::Size(this->chartobject_ptr->Get_PanelWidth(), chartobject_ptr->Get_PanelHeight()); this->Controls->Add(this->zg1); this->Name = L"Form1"; this->StartPosition = System::Windows::Forms::FormStartPosition::WindowsDefaultLocation;//:CenterScreen; //this->Text = L"PHREEQC chart"; System::String ^desc = gcnew String(this->chartobject_ptr->Get_description().c_str()); this->Text = L"Phreeqc USER_GRAPH " + this->chartobject_ptr->Get_n_user() + " " + desc; this->TopMost = false; System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid)); try { //this->Icon = gcnew System::Drawing::Icon("c:\\phreeqc\\phreex.ico"); this->Icon = (cli::safe_cast(resources->GetObject(L"$this.Icon"))); } catch (...) { } this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &Form1::MyFormClosingEventHandler); this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load); this->Resize += gcnew System::EventHandler(this, &Form1::Form1_Resize); this->ResumeLayout(false); } #pragma endregion }; }