diff --git a/pwiz_tools/Skyline/Controls/PopupPickList.cs b/pwiz_tools/Skyline/Controls/PopupPickList.cs index 5b63ea2957..fe0259c7bb 100644 --- a/pwiz_tools/Skyline/Controls/PopupPickList.cs +++ b/pwiz_tools/Skyline/Controls/PopupPickList.cs @@ -493,6 +493,7 @@ public void ToggleItem(int iChange) public void SetItemChecked(int i, bool checkItem) { SetItemCheckedInternal(i, checkItem); + pickListMulti.SelectedIndex = i; pickListMulti.Invalidate(pickListMulti.GetItemRectangle(i)); UpdateSelectAll(); diff --git a/pwiz_tools/Skyline/Controls/SequenceTree.cs b/pwiz_tools/Skyline/Controls/SequenceTree.cs index a78311742c..2d849b7d68 100644 --- a/pwiz_tools/Skyline/Controls/SequenceTree.cs +++ b/pwiz_tools/Skyline/Controls/SequenceTree.cs @@ -212,6 +212,11 @@ public bool IsTipVisible get { return _nodeTip.Visible; } } + public Rectangle TipRect + { + get { return _nodeTip.Visible ? _nodeTip.Bounds : Rectangle.Empty; } + } + [Browsable(true)] public event EventHandler PickedChildrenEvent; diff --git a/pwiz_tools/Skyline/EditUI/PasteDlg.cs b/pwiz_tools/Skyline/EditUI/PasteDlg.cs index 0301675576..09906ca2e0 100644 --- a/pwiz_tools/Skyline/EditUI/PasteDlg.cs +++ b/pwiz_tools/Skyline/EditUI/PasteDlg.cs @@ -154,6 +154,21 @@ private DataGridView ActiveGridView } } + public void SelectCell(int row, int column) + { + ActiveGridView.CurrentCell = ActiveGridView.Rows[row].Cells[column]; + } + + public void SetColumnWidths(params int[] columnWidths) + { + for (int i = 0; i < columnWidths.Length; i++) + { + int width = columnWidths[i]; + if (width != -1) + ActiveGridView.Columns[i].Width = width; + } + } + public void ShowError(PasteError pasteError) { _noErrors = false; diff --git a/pwiz_tools/Skyline/EditUI/UniquePeptidesDlg.cs b/pwiz_tools/Skyline/EditUI/UniquePeptidesDlg.cs index 80b5ccbe62..2543d5c0fd 100644 --- a/pwiz_tools/Skyline/EditUI/UniquePeptidesDlg.cs +++ b/pwiz_tools/Skyline/EditUI/UniquePeptidesDlg.cs @@ -708,6 +708,12 @@ public DataGridView GetDataGridView() return dataGridView1; } + public int SplitHeight + { + get { return splitContainer1.SplitterDistance; } + set { splitContainer1.SplitterDistance = value; } + } + public void SelectUnique(UniquenessType uniquenessType) { SelectPeptidesWithNumberOfMatchesAtOrBelowThreshold(1, uniquenessType); diff --git a/pwiz_tools/Skyline/Skyline.cs b/pwiz_tools/Skyline/Skyline.cs index c067f29d51..3fa3600e0b 100644 --- a/pwiz_tools/Skyline/Skyline.cs +++ b/pwiz_tools/Skyline/Skyline.cs @@ -4161,7 +4161,15 @@ public bool StatusContains(string format) return statusGeneral.Text.Contains(start) && statusGeneral.Text.Contains(end); } - public int StatusBarHeight { get { return statusGeneral.Height; } } + public int StatusBarHeight { get { return statusStrip.Height; } } + + public int StatusSelectionWidth + { + get + { + return statusSequences.Width + statusPeptides.Width + statusPrecursors.Width + statusIons.Width + 20; + } + } #endregion diff --git a/pwiz_tools/Skyline/SkylineTester/SkylineTesterWindow.Designer.cs b/pwiz_tools/Skyline/SkylineTester/SkylineTesterWindow.Designer.cs index e741da7c75..3b0e2332d6 100644 --- a/pwiz_tools/Skyline/SkylineTester/SkylineTesterWindow.Designer.cs +++ b/pwiz_tools/Skyline/SkylineTester/SkylineTesterWindow.Designer.cs @@ -1364,6 +1364,7 @@ private void InitializeComponent() "Quality", "Demo", "Screenshots", + "Auto-Screenshots", "Covershot"}); this.runMode.Location = new System.Drawing.Point(276, 553); this.runMode.Name = "runMode"; diff --git a/pwiz_tools/Skyline/SkylineTester/TabTests.cs b/pwiz_tools/Skyline/SkylineTester/TabTests.cs index 535c5dee46..20d5f2af27 100644 --- a/pwiz_tools/Skyline/SkylineTester/TabTests.cs +++ b/pwiz_tools/Skyline/SkylineTester/TabTests.cs @@ -72,6 +72,8 @@ public override bool Run() args.Append(" pause=-1"); // Magic number that tells TestRunner to pause and show UI for a manual screenshot if (Equals(MainWindow.RunTestMode.SelectedItem.ToString(), "Covershot")) args.Append(" pause=-2"); // Magic number that tells TestRunner to grab tutorial cover shot then move on to next test + if (Equals(MainWindow.RunTestMode.SelectedItem.ToString(), "Auto-Screenshots")) + args.Append(" pause=-3"); // Magic number that tells TestRunner to save the screenshot to the tutorials folder if (MainWindow.TestsRunSmallMoleculeVersions.Checked) args.Append(" runsmallmoleculeversions=on"); diff --git a/pwiz_tools/Skyline/TestPerf/DdaTutorialTest.cs b/pwiz_tools/Skyline/TestPerf/DdaTutorialTest.cs index ff349bfc89..05d48af07e 100644 --- a/pwiz_tools/Skyline/TestPerf/DdaTutorialTest.cs +++ b/pwiz_tools/Skyline/TestPerf/DdaTutorialTest.cs @@ -98,10 +98,11 @@ protected override void DoTest() private Image _searchLogImage; - protected override void ProcessCoverShot(Bitmap bmp) + protected override Bitmap ProcessCoverShot(Bitmap bmp) { var graph = Graphics.FromImage(bmp); graph.DrawImageUnscaled(_searchLogImage, bmp.Width - _searchLogImage.Width - 10, bmp.Height - _searchLogImage.Height - 30); + return bmp; } /// @@ -278,7 +279,7 @@ private void TestMsFraggerSearch() if (IsCoverShotMode) { RunUI(() => importPeptideSearchDlg.Width = 404); - _searchLogImage = ScreenshotManager.TakeNextShot(importPeptideSearchDlg); + _searchLogImage = ScreenshotManager.TakeShot(importPeptideSearchDlg); Assert.IsNotNull(_searchLogImage); } diff --git a/pwiz_tools/Skyline/TestPerf/DiaSearchTutorialTest.cs b/pwiz_tools/Skyline/TestPerf/DiaSearchTutorialTest.cs index df950042e1..3eacecc8a8 100644 --- a/pwiz_tools/Skyline/TestPerf/DiaSearchTutorialTest.cs +++ b/pwiz_tools/Skyline/TestPerf/DiaSearchTutorialTest.cs @@ -197,10 +197,11 @@ protected override void DoTest() private Image _searchLogImage; - protected override void ProcessCoverShot(Bitmap bmp) + protected override Bitmap ProcessCoverShot(Bitmap bmp) { var graph = Graphics.FromImage(bmp); graph.DrawImageUnscaled(_searchLogImage, bmp.Width - _searchLogImage.Width - 10, bmp.Height - _searchLogImage.Height - 30); + return bmp; } /// @@ -429,7 +430,7 @@ private void TestMsFraggerSearch() if (IsCoverShotMode) { RunUI(() => importPeptideSearchDlg.Width = 404); - _searchLogImage = ScreenshotManager.TakeNextShot(importPeptideSearchDlg); + _searchLogImage = ScreenshotManager.TakeShot(importPeptideSearchDlg); Assert.IsNotNull(_searchLogImage); } diff --git a/pwiz_tools/Skyline/TestTutorial/AbsoluteQuantTutorialTest.cs b/pwiz_tools/Skyline/TestTutorial/AbsoluteQuantTutorialTest.cs index 6ab2e348b0..736473571b 100644 --- a/pwiz_tools/Skyline/TestTutorial/AbsoluteQuantTutorialTest.cs +++ b/pwiz_tools/Skyline/TestTutorial/AbsoluteQuantTutorialTest.cs @@ -67,6 +67,8 @@ public void TestAbsoluteQuantificationTutorial() RunFunctionalTest(); } + protected override int[] NonScreenShotFigures => new[] { 1 }; + private string GetTestPath(string relativePath) { var dataFolder = UseRawFiles ? "AbsoluteQuant" : "AbsoluteQuantMzml"; // Not L10N @@ -158,17 +160,20 @@ protected override void DoTest() // Importing RAW files into Skyline p. 11, 12 var importResultsDlg = ShowDialog(SkylineWindow.ImportResults); - PauseForScreenShot("Import Results - click OK to get shot of Import Results Files and then cancel", 11); + PauseForScreenShot("Import Results", 11); + var importResultsFilesDlg = ShowDialog(importResultsDlg.OkDialog); RunUI(() => { var rawFiles = DataSourceUtil.GetDataSources(TestFilesDirs[0].FullPath).First().Value.Skip(1); - var namedPathSets = from rawFile in rawFiles - select new KeyValuePair( - rawFile.GetFileNameWithoutExtension(), new[] { rawFile }); - importResultsDlg.NamedPathSets = namedPathSets.ToArray(); + foreach (var rawFile in rawFiles) + { + importResultsFilesDlg.SelectFile(rawFile.GetFileName()); + } }); - RunDlg(importResultsDlg.OkDialog, + PauseForScreenShot("Import Results Files", 12); + + RunDlg(importResultsFilesDlg.Open, importResultsNameDlg => importResultsNameDlg.NoDialog()); WaitForGraphs(); @@ -265,7 +270,7 @@ protected override void DoTest() // Peptide Quantitification Settings p. 16 peptideSettingsUi = ShowDialog(SkylineWindow.ShowPeptideSettingsUI); - RunUI(() => peptideSettingsUi.SelectedTab = (PeptideSettingsUI.TABS)5); + RunUI(() => peptideSettingsUi.SelectedTab = PeptideSettingsUI.TABS.Quantification); const string quantUnits = "fmol/ul"; RunUI(() => { @@ -273,7 +278,7 @@ protected override void DoTest() peptideSettingsUi.QuantNormalizationMethod = new NormalizationMethod.RatioToLabel(IsotopeLabelType.heavy); peptideSettingsUi.QuantUnits = quantUnits; }); - PauseForScreenShot("Peptide Settings Quantification Tab", 16); + PauseForScreenShot("Peptide Settings Quantification Tab", 16); OkDialog(peptideSettingsUi, peptideSettingsUi.OkDialog); // Specify analyte concentrations of external standards @@ -315,7 +320,7 @@ protected override void DoTest() gridFloatingWindow.Top = SkylineWindow.Top; gridFloatingWindow.Left = SkylineWindow.Right + 20; }); - PauseForScreenShot("Document grid with concentrations filled in", 17); + PauseForScreenShot("Document grid with concentrations filled in", 17); } // View the calibration curve p. 18 @@ -354,7 +359,7 @@ protected override void DoTest() calibrationFloatingWindow.Top = SkylineWindow.Top; calibrationFloatingWindow.Left = SkylineWindow.Right + 20; }); - PauseForScreenShot("View calibration curve", 18); + PauseForScreenShot("View calibration curve", 18); } Assert.AreEqual(CalibrationCurveFitter.AppendUnits(QuantificationStrings.Analyte_Concentration, quantUnits), calibrationForm.ZedGraphControl.GraphPane.XAxis.Title.Text); diff --git a/pwiz_tools/Skyline/TestTutorial/DiaTutorialTest.cs b/pwiz_tools/Skyline/TestTutorial/DiaTutorialTest.cs index 60bbbf8b19..b562e70130 100644 --- a/pwiz_tools/Skyline/TestTutorial/DiaTutorialTest.cs +++ b/pwiz_tools/Skyline/TestTutorial/DiaTutorialTest.cs @@ -17,11 +17,13 @@ * limitations under the License. */ +using System; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Windows.Forms; +using DigitalRune.Windows.Docking; using Microsoft.VisualStudio.TestTools.UnitTesting; using pwiz.Skyline.Alerts; using pwiz.Skyline.Controls; @@ -48,7 +50,7 @@ public class DiaTutorialTest : AbstractFunctionalTestEx /// to regenerate checkpoint files for non-full-import mode, /// when something changes in the test. /// - private bool IsFullImportMode { get { return IsRecordImported || IsCoverShotMode || IsPauseForScreenShots; } } + private bool IsFullImportMode { get { return IsRecordImported || IsCoverShotMode || IsPauseForScreenShots || IsAutoScreenShotMode; } } private bool IsRecordImported { @@ -59,7 +61,7 @@ private bool IsRecordImported public void TestDiaTutorial() { // Set true to look at tutorial screenshots. -// IsPauseForScreenShots = true; + IsPauseForScreenShots = true; // IsCoverShotMode = true; CoverShotName = "DIA"; // PauseStartPage = 36; @@ -252,7 +254,7 @@ protected override void DoTest() var peptidesPerProteinDlg = ShowDialog(() => importPeptideSearchDlg.ClickNextButton()); WaitForCondition(() => peptidesPerProteinDlg.DocumentFinalCalculated); - PauseForScreenShot("Peptides per protein form", 25); + PauseForScreenShot("Peptides per protein form", 25); RunUI(() => { int proteinCount, peptideCount, precursorCount, transitionCount; @@ -317,7 +319,7 @@ protected override void DoTest() }); RestoreViewOnScreen(27); - PauseForScreenShot("Skyline window", 27); + PauseForScreenShot("Skyline window", 27); RunUI(() => { @@ -325,7 +327,7 @@ protected override void DoTest() SkylineWindow.ChangeMassErrorTransition(TransitionMassError.all); }); WaitForGraphs(); - PauseForScreenShot("Mass Errors: Histogram metafile", 28); + PauseForGraphScreenShot("Mass Errors: Histogram metafile", FindGraphSummaryByGraphType(), 28); RunUI(() => { ValidateMassErrorStatistics(2.7, 3.3); @@ -346,7 +348,7 @@ protected override void DoTest() RunUI(() => SkylineWindow.SequenceTree.SelectedNode = SkylineWindow.SelectedNode.Parent); WaitForGraphs(); RunUI(() => SkylineWindow.SequenceTree.SelectedNode = SkylineWindow.SelectedNode.Nodes[0]); - PauseForScreenShot("Skyline window - with manual integration and ID times", 29); + PauseForScreenShot("Skyline window - with manual integration and ID times", 29); RunUI(() => { @@ -355,7 +357,7 @@ protected override void DoTest() }); RestoreViewOnScreen(31); SelectNode(SrmDocument.Level.Molecules, 1); // 2nd peptide - PauseForScreenShot("Chromatogram graph metafile", 31); + PauseForGraphScreenShot("Chromatogram graph metafile", SkylineWindow.GetGraphChrom("Pit01"), 31); RestoreViewOnScreen(27); RunUI(() => @@ -364,7 +366,7 @@ protected override void DoTest() SkylineWindow.Height = 700; }); SelectNode(SrmDocument.Level.TransitionGroups, 1); // 2nd peptide - first precursor - PauseForScreenShot("Skyline window", 32); + PauseForScreenShot("Skyline window", 32); SelectNode(SrmDocument.Level.Transitions, 22); @@ -374,7 +376,8 @@ protected override void DoTest() SkylineWindow.Height = 463; }); - PauseForScreenShot("Product ion chromatogram graph metafiles", 33); + PauseForGraphScreenShot("Product ion chromatogram graph metafile 1", SkylineWindow.GetGraphChrom("Pit01"), 33); + PauseForGraphScreenShot("Product ion chromatogram graph metafile 2", SkylineWindow.GetGraphChrom("Pit02"), 33); RunUI(() => { @@ -386,11 +389,19 @@ protected override void DoTest() ChangePeakBounds("Pit01", 65.36, 66.7); ChangePeakBounds("Pit02", 64.89, 66.2); - PauseForScreenShot("Chromatograms and peak areas", 34); + Func clipChromAndPeakAreas = bmp => + ClipSkylineWindowShotWithForms(bmp, new DockableForm[] + { + SkylineWindow.GetGraphChrom("Pit01"), + SkylineWindow.GetGraphChrom("Pit02"), + FindGraphSummaryByGraphType() + }); + + PauseForScreenShot("Chromatograms and peak areas", 34, null, clipChromAndPeakAreas); SelectNode(SrmDocument.Level.TransitionGroups, 13); - PauseForScreenShot("Chromatograms and peak areas", 35); + PauseForScreenShot("Chromatograms and peak areas", 35, null, clipChromAndPeakAreas); if (IsCoverShotMode) { @@ -442,15 +453,14 @@ protected override void DoTest() RestoreViewOnScreen(36); ClickChromatogram("Pit01", 70.19, 169.5E+06, PaneKey.PRECURSORS); - PauseForScreenShot("Full-Scan MS1 spectrum metafile", 36); - + PauseForGraphScreenShot("Full-Scan MS1 spectrum metafile", SkylineWindow.GraphFullScan, 36); ClickChromatogram("Pit01", 70.79, 4.9E+05, PaneKey.PRODUCTS); - PauseForScreenShot("Full-Scan MS/MS spectrum y10 metafile", 37); + PauseForGraphScreenShot("Full-Scan MS/MS spectrum y10 metafile", SkylineWindow.GraphFullScan, 37); ClickChromatogram("Pit01", 70.79, 3.25E+05, PaneKey.PRODUCTS); - PauseForScreenShot("Full-Scan MS/MS spectrum y10++ metafile", 38); + PauseForGraphScreenShot("Full-Scan MS/MS spectrum y10++ metafile", SkylineWindow.GraphFullScan, 38); FindNode("K.ELVYETVR.V [73, 80]"); WaitForGraphs(); @@ -462,13 +472,13 @@ protected override void DoTest() SkylineWindow.GraphFullScan.SetMzScale(new MzRange(504, 506)); SkylineWindow.GraphFullScan.Parent.Parent.Height -= 15; // Not quite as tall to fit 3 into one page }); - PauseForScreenShot("Full-Scan MS1 spectrum metafile (1/3)", 39); + PauseForGraphScreenShot("Full-Scan MS1 spectrum metafile (1/3)", SkylineWindow.GraphFullScan, 39); MoveNextScan(41.68); - PauseForScreenShot("Full-Scan MS1 spectrum metafile (2/3)", 39); + PauseForGraphScreenShot("Full-Scan MS1 spectrum metafile (2/3)", SkylineWindow.GraphFullScan, 39); MoveNextScan(41.7); - PauseForScreenShot("Full-Scan MS1 spectrum metafile (3/3)", 39); + PauseForGraphScreenShot("Full-Scan MS1 spectrum metafile (3/3)", SkylineWindow.GraphFullScan, 39); } // Clear all the settings lists that were defined in this tutorial diff --git a/pwiz_tools/Skyline/TestTutorial/ExistingExperimentsTutorialTest.cs b/pwiz_tools/Skyline/TestTutorial/ExistingExperimentsTutorialTest.cs index 34617db5fa..9655916fd3 100644 --- a/pwiz_tools/Skyline/TestTutorial/ExistingExperimentsTutorialTest.cs +++ b/pwiz_tools/Skyline/TestTutorial/ExistingExperimentsTutorialTest.cs @@ -73,11 +73,12 @@ public void TestExistingExperimentsTutorial() RunFunctionalTest(); } - protected override void ProcessCoverShot(Bitmap bmp) + protected override Bitmap ProcessCoverShot(Bitmap bmp) { var excelBmp = new Bitmap(TestContext.GetProjectDirectory(@"TestTutorial\ExistingQuant_excel.png")); var graph = Graphics.FromImage(bmp); graph.DrawImageUnscaled(excelBmp, bmp.Width - excelBmp.Width, bmp.Height - excelBmp.Height); + return bmp; } // Not L10N diff --git a/pwiz_tools/Skyline/TestTutorial/MethodEditTutorialTest.cs b/pwiz_tools/Skyline/TestTutorial/MethodEditTutorialTest.cs index e0d016dd69..60280edd7c 100644 --- a/pwiz_tools/Skyline/TestTutorial/MethodEditTutorialTest.cs +++ b/pwiz_tools/Skyline/TestTutorial/MethodEditTutorialTest.cs @@ -29,7 +29,6 @@ using pwiz.Skyline; using pwiz.Skyline.Alerts; using pwiz.Skyline.Controls; -using pwiz.Skyline.Controls.Graphs; using pwiz.Skyline.Controls.SeqNode; using pwiz.Skyline.EditUI; using pwiz.Skyline.FileUI; @@ -204,7 +203,8 @@ protected override void DoTest() PauseForScreenShot("Transition Settings - Library tab", 10); // Not L10N OkDialog(transitionSettingsUI, transitionSettingsUI.OkDialog); } - PauseForScreenShot("Targets tree clipped from main window", 11); // Not L10N + // TODO: Crop the screenshot to get rid of the title and scrollbars + PauseForScreenShot("Targets tree clipped from main window", 11); // Not L10N if (IsCoverShotMode) { @@ -287,6 +287,11 @@ protected override void DoTest() pasteProteinsDlg.SelectedPath = SkylineWindow.SequenceTree.SelectedPath; pasteProteinsDlg.PasteProteins(); }); + RunUI(() => + { + pasteProteinsDlg.SelectCell(17, 0); + pasteProteinsDlg.SetColumnWidths(-1, 220, 500, 0, 0, 0, 0); + }); PauseForScreenShot("Insert Protein List - For Screenshot, select last (empty) item in list", 14); // Not L10N OkDialog(pasteProteinsDlg, pasteProteinsDlg.OkDialog); } @@ -324,6 +329,11 @@ protected override void DoTest() RunUI(() => SkylineWindow.Undo()); PasteDlg pastePeptidesDlg = ShowDialog(SkylineWindow.ShowPastePeptidesDlg); RunUI(pastePeptidesDlg.PastePeptides); + RunUI(() => + { + pastePeptidesDlg.SelectCell(12, 0); + pastePeptidesDlg.Height = 437; + }); PauseForScreenShot("Insert Peptide List - For screenshot, select last (empty) line in list", 17); // Not L10N OkDialog(pastePeptidesDlg, pastePeptidesDlg.OkDialog); } @@ -336,7 +346,7 @@ protected override void DoTest() findPeptideDlg.FindNext(); findPeptideDlg.Close(); }); - PauseForScreenShot("Library Match graph metafile", 18); // Not L10N + PauseForGraphScreenShot("Library Match graph metafile", SkylineWindow.GraphSpectrum, 18); // Not L10N using (new CheckDocumentState(35, 64, 64, 320, null, true)) { @@ -344,7 +354,8 @@ protected override void DoTest() PauseForForm(typeof(RefineDlg.DocumentTab)); RunUI(() => refineDlg.MinTransitions = 5); OkDialog(refineDlg, refineDlg.OkDialog); - PauseForScreenShot("29/35 prot 50/64 pep 50/64 prec 246/320 tran", 18); // Not L10N + PauseForScreenShot("29/35 prot 50/64 pep 50/64 prec 246/320 tran", 18, null, + ClipSelectionStatus); // Not L10N } // Checking Peptide Uniqueness, p. 18 @@ -362,6 +373,9 @@ protected override void DoTest() { Assert.AreEqual(1, uniquePeptidesDlg.GetDataGridView().RowCount); Assert.AreEqual(7, uniquePeptidesDlg.GetDataGridView().ColumnCount); + + uniquePeptidesDlg.SplitHeight = 58; + uniquePeptidesDlg.Height = 292; }); PauseForScreenShot("Unique Peptides form", 19); // Not L10N var oldDoc = SkylineWindow.Document; @@ -371,14 +385,12 @@ protected override void DoTest() } // Protein Name Auto-Completion - PauseForScreenShot("(fig. 1): For screenshot, click at bottom of document tree, type 'ybl087' and see the autocomplete text. Make sure to undo this new entry before proceeding.", 20); // Not L10N - TestAutoComplete("ybl087", 0); // Not L10N + TestAutoComplete("ybl087", 0, 20); // Not L10N var peptideGroups = new List(Program.ActiveDocument.PeptideGroups); Assert.AreEqual("YBL087C", peptideGroups[peptideGroups.Count - 1].Name); // Not L10N // Protein Description Auto-Completion - PauseForScreenShot("(fig. 2): For screenshot, click at bottom of document tree, type 'eft2' and see the autocomplete text, then down-arrow twice. Make sure to undo this new entry before proceeding.", 20); // Not L10N - TestAutoComplete("eft2", 0); // Sorting logic puts this at the 0th entry in the list - Not L10N + TestAutoComplete("eft2", 0, 20); // Sorting logic puts this at the 0th entry in the list - Not L10N peptideGroups = new List(Program.ActiveDocument.PeptideGroups); Assert.AreEqual("YDR385W", peptideGroups[peptideGroups.Count - 1].Name); // Not L10N @@ -386,7 +398,9 @@ protected override void DoTest() TestAutoComplete("IQGP", 0); // Not L10N var peptides = new List(Program.ActiveDocument.Peptides); Assert.AreEqual("K.AYLPVNESFGFTGELR.Q [770, 785]", peptides[peptides.Count - 1].Peptide.ToString()); // Not L10N - PauseForScreenShot("(fig. 1) - For screenshot, click at the bottom of the document tree", 21); // Not L10N + RestoreViewOnScreen(21); + PauseForScreenShot("(fig. 1) - Added targets", 21, null, + bmp => ClipBitmap(bmp, new Rectangle(5, bmp.Height - 178, 355, 165))); // Not L10N // Pop-up Pick-Lists, p. 21 using (new CheckDocumentState(36, 71, 71, 355, null, true)) @@ -444,10 +458,9 @@ protected override void DoTest() }); FindNode(string.Format("L [b5] - {0:F04}+", 484.3130)); // Not L10N - may be localized " (rank 3)" - ShowNodeTip("YBL087C"); - ShowNodeTip(string.Format("{0:F04}+++", 672.6716)); + ShowNodeTip("YBL087C", 23); + ShowNodeTip(string.Format("{0:F04}+++", 672.6716), 23); ShowNodeTip(null); - PauseForScreenShot("For Screenshots, First hover over YBL087C, then over 672.671+++", 23); // Not L10N // Preparing to Measure, p. 25 RunDlg(() => SkylineWindow.ShowTransitionSettingsUI(TransitionSettingsUI.TABS.Prediction), transitionSettingsUI => @@ -500,7 +513,7 @@ private void VerifyPrecursorLibrary(int indexPrecursor, string libraryName, doub }); } - private void ShowNodeTip(string nodeText) + private void ShowNodeTip(string nodeText, int? pageNumPause = null) { RunUI(() => { @@ -519,6 +532,20 @@ private void ShowNodeTip(string nodeText) SkylineWindow.SequenceTree.MoveMouse(pt); }); WaitForConditionUI(NodeTip.TipDelayMs * 10, () => SkylineWindow.SequenceTree.IsTipVisible); + + if (pageNumPause != null) + { + PauseForScreenShot("Tip for " + nodeText, pageNumPause.Value, null, + bmp => + { + var cropRect = SkylineWindow.SequenceTree.TipRect; + // Remove lower-right shadow + cropRect.Width -= 4; + cropRect.Height -= 4; + return ClipBitmap(bmp, cropRect); + }); + } + SkylineWindow.SequenceTree.IgnoreFocus = false; // If someone is watching let them at least see the tips, if not take screenshots of them int delayMultiplier = IsPauseForScreenShots ? 4 : 1; @@ -548,7 +575,7 @@ private void SetClipboardFileText(string filepath) SetClipboardTextUI(File.ReadAllText(TestFilesDirs[0].GetTestPath(filepath))); } - private static void TestAutoComplete(string text, int index) + private void TestAutoComplete(string text, int index, int? pageNum = null) { var doc = WaitForDocumentLoaded(); RunUI(() => @@ -560,6 +587,8 @@ private static void TestAutoComplete(string text, int index) }); var statementCompletionForm = WaitForOpenForm(); Assert.IsNotNull(statementCompletionForm); + if (pageNum != null) + PauseForScreenShot("Auto-complete " + text, pageNum.Value); RunUI(() => SkylineWindow.SequenceTree.StatementCompletionEditBox.OnSelectionMade( (StatementCompletionItem)statementCompletionForm.ListView.Items[index].Tag)); WaitForDocumentChangeLoaded(doc); diff --git a/pwiz_tools/Skyline/TestTutorial/MethodEditViews.zip b/pwiz_tools/Skyline/TestTutorial/MethodEditViews.zip index 1b67c5c67b..fe20591e0d 100644 Binary files a/pwiz_tools/Skyline/TestTutorial/MethodEditViews.zip and b/pwiz_tools/Skyline/TestTutorial/MethodEditViews.zip differ diff --git a/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.Designer.cs b/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.Designer.cs index 920afc3783..2d03e95437 100644 --- a/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.Designer.cs +++ b/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.Designer.cs @@ -33,16 +33,18 @@ private void InitializeComponent() this.btnContinue = new System.Windows.Forms.Button(); this.lblDescription = new System.Windows.Forms.Label(); this.lblDescriptionLink = new System.Windows.Forms.LinkLabel(); - this.btnCopyToClipBoard = new System.Windows.Forms.Button(); + this.btnScreenshot = new System.Windows.Forms.Button(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); - this.btnCopyMetafileToClipboard = new System.Windows.Forms.Button(); + this.saveScreenshotCheckbox = new System.Windows.Forms.CheckBox(); + this.btnScreenshotAndContinue = new System.Windows.Forms.Button(); + this.btnPreview = new System.Windows.Forms.Button(); this.SuspendLayout(); // // btnContinue // - this.btnContinue.Location = new System.Drawing.Point(12, 32); + this.btnContinue.Location = new System.Drawing.Point(18, 54); this.btnContinue.Name = "btnContinue"; - this.btnContinue.Size = new System.Drawing.Size(75, 23); + this.btnContinue.Size = new System.Drawing.Size(208, 35); this.btnContinue.TabIndex = 0; this.btnContinue.Text = "Continue"; this.btnContinue.UseVisualStyleBackColor = true; @@ -52,65 +54,89 @@ private void InitializeComponent() // this.lblDescription.AutoEllipsis = true; this.lblDescription.AutoSize = true; - this.lblDescription.Location = new System.Drawing.Point(13, 13); + this.lblDescription.Location = new System.Drawing.Point(20, 20); + this.lblDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.lblDescription.Name = "lblDescription"; - this.lblDescription.Size = new System.Drawing.Size(60, 13); + this.lblDescription.Size = new System.Drawing.Size(89, 20); this.lblDescription.TabIndex = 1; this.lblDescription.Text = "Description"; // // lblDescriptionLink // this.lblDescriptionLink.AutoSize = true; - this.lblDescriptionLink.Location = new System.Drawing.Point(32, 13); + this.lblDescriptionLink.Location = new System.Drawing.Point(48, 20); + this.lblDescriptionLink.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.lblDescriptionLink.Name = "lblDescriptionLink"; - this.lblDescriptionLink.Size = new System.Drawing.Size(60, 13); + this.lblDescriptionLink.Size = new System.Drawing.Size(89, 20); this.lblDescriptionLink.TabIndex = 2; this.lblDescriptionLink.TabStop = true; this.lblDescriptionLink.Text = "Description"; this.lblDescriptionLink.Visible = false; this.lblDescriptionLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lblDescriptionLink_LinkClicked); // - // btnCopyToClipBoard - // - this.btnCopyToClipBoard.Enabled = false; - this.btnCopyToClipBoard.Location = new System.Drawing.Point(12, 61); - this.btnCopyToClipBoard.Name = "btnCopyToClipBoard"; - this.btnCopyToClipBoard.Size = new System.Drawing.Size(75, 23); - this.btnCopyToClipBoard.TabIndex = 3; - this.btnCopyToClipBoard.Text = "Copy Form"; - this.toolTip1.SetToolTip(this.btnCopyToClipBoard, resources.GetString("btnCopyToClipBoard.ToolTip")); - this.btnCopyToClipBoard.UseVisualStyleBackColor = true; - this.btnCopyToClipBoard.Visible = false; - this.btnCopyToClipBoard.Click += new System.EventHandler(this.btnCopyToClipboard_Click); - // - // btnCopyMetafileToClipboard - // - this.btnCopyMetafileToClipboard.Enabled = false; - this.btnCopyMetafileToClipboard.Location = new System.Drawing.Point(12, 90); - this.btnCopyMetafileToClipboard.Name = "btnCopyMetafileToClipboard"; - this.btnCopyMetafileToClipboard.Size = new System.Drawing.Size(75, 23); - this.btnCopyMetafileToClipboard.TabIndex = 4; - this.btnCopyMetafileToClipboard.Text = "Copy Graph"; - this.toolTip1.SetToolTip(this.btnCopyMetafileToClipboard, "Copies metafile to clipboard"); - this.btnCopyMetafileToClipboard.UseVisualStyleBackColor = true; - this.btnCopyMetafileToClipboard.Visible = false; - this.btnCopyMetafileToClipboard.Click += new System.EventHandler(this.btnCopyMetaFileToClipboard_Click); + // btnScreenshot + // + this.btnScreenshot.Location = new System.Drawing.Point(18, 136); + this.btnScreenshot.Name = "btnScreenshot"; + this.btnScreenshot.Size = new System.Drawing.Size(208, 35); + this.btnScreenshot.TabIndex = 3; + this.btnScreenshot.Text = "Save Screenshot"; + this.toolTip1.SetToolTip(this.btnScreenshot, resources.GetString("btnScreenshot.ToolTip")); + this.btnScreenshot.UseVisualStyleBackColor = true; + this.btnScreenshot.Click += new System.EventHandler(this.btnScreenshot_Click); + // + // saveScreenshotCheckbox + // + this.saveScreenshotCheckbox.AutoSize = true; + this.saveScreenshotCheckbox.Checked = true; + this.saveScreenshotCheckbox.CheckState = System.Windows.Forms.CheckState.Checked; + this.saveScreenshotCheckbox.Location = new System.Drawing.Point(46, 222); + this.saveScreenshotCheckbox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.saveScreenshotCheckbox.Name = "saveScreenshotCheckbox"; + this.saveScreenshotCheckbox.Size = new System.Drawing.Size(157, 24); + this.saveScreenshotCheckbox.TabIndex = 6; + this.saveScreenshotCheckbox.Text = "Save Screenshot"; + this.saveScreenshotCheckbox.UseVisualStyleBackColor = true; + this.saveScreenshotCheckbox.CheckedChanged += new System.EventHandler(this.saveScreenshotCheckbox_CheckedChanged); + // + // btnScreenshotAndContinue + // + this.btnScreenshotAndContinue.Location = new System.Drawing.Point(18, 177); + this.btnScreenshotAndContinue.Name = "btnScreenshotAndContinue"; + this.btnScreenshotAndContinue.Size = new System.Drawing.Size(208, 35); + this.btnScreenshotAndContinue.TabIndex = 7; + this.btnScreenshotAndContinue.Text = "Save and Continue"; + this.btnScreenshotAndContinue.UseVisualStyleBackColor = true; + this.btnScreenshotAndContinue.Click += new System.EventHandler(this.btnScreenshotAndContinue_Click); + // + // btnPreview + // + this.btnPreview.Location = new System.Drawing.Point(18, 95); + this.btnPreview.Name = "btnPreview"; + this.btnPreview.Size = new System.Drawing.Size(208, 35); + this.btnPreview.TabIndex = 8; + this.btnPreview.Text = "Preview"; + this.btnPreview.UseVisualStyleBackColor = true; + this.btnPreview.Click += new System.EventHandler(this.btnPreview_Click); // // PauseAndContinueForm // this.AcceptButton = this.btnContinue; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; - this.ClientSize = new System.Drawing.Size(174, 128); + this.ClientSize = new System.Drawing.Size(304, 273); this.ControlBox = false; - this.Controls.Add(this.btnCopyMetafileToClipboard); - this.Controls.Add(this.btnCopyToClipBoard); + this.Controls.Add(this.btnPreview); + this.Controls.Add(this.btnScreenshotAndContinue); + this.Controls.Add(this.saveScreenshotCheckbox); + this.Controls.Add(this.btnScreenshot); this.Controls.Add(this.lblDescriptionLink); this.Controls.Add(this.lblDescription); this.Controls.Add(this.btnContinue); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.KeyPreview = true; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "PauseAndContinueForm"; @@ -127,8 +153,10 @@ private void InitializeComponent() private System.Windows.Forms.Button btnContinue; private System.Windows.Forms.Label lblDescription; private System.Windows.Forms.LinkLabel lblDescriptionLink; - private System.Windows.Forms.Button btnCopyToClipBoard; + private System.Windows.Forms.Button btnScreenshot; private System.Windows.Forms.ToolTip toolTip1; - private System.Windows.Forms.Button btnCopyMetafileToClipboard; + private System.Windows.Forms.CheckBox saveScreenshotCheckbox; + private System.Windows.Forms.Button btnScreenshotAndContinue; + private System.Windows.Forms.Button btnPreview; } } \ No newline at end of file diff --git a/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.cs b/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.cs index 338bcd21b0..6870f3e91b 100644 --- a/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.cs +++ b/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.cs @@ -18,16 +18,16 @@ */ using System; +using System.Drawing; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; -using DigitalRune.Windows.Docking; using pwiz.Common.SystemUtil; using pwiz.Skyline; -using pwiz.Skyline.Controls.Graphs; using pwiz.Skyline.Controls.Startup; -using pwiz.Skyline.EditUI; using pwiz.Skyline.Util; using pwiz.Skyline.Util.Extensions; @@ -35,35 +35,26 @@ namespace pwiz.SkylineTestUtil { public partial class PauseAndContinueForm : Form { + private static ScreenshotPreviewForm screenshotPreviewForm = new ScreenshotPreviewForm(); private readonly string _linkUrl; private readonly bool _showMatchingPage; - private Form _screenshotForm; + private readonly string _fileToSave; + private Control _screenshotForm; + private bool _fullScreen; private ScreenshotManager _screenshotManager; + private Func _processShot; - public PauseAndContinueForm(string description = null, string link = null, bool showMatchingPages = false, Form screenshotForm = null, ScreenshotManager screenshotManager = null) + public PauseAndContinueForm(string description, string fileToSave, string link, bool showMatchingPages, + Control screenshotForm, bool fullScreen, ScreenshotManager screenshotManager, Func processShot) { InitializeComponent(); _screenshotForm = screenshotForm; + _fullScreen = fullScreen; _screenshotManager = screenshotManager; + _fileToSave = fileToSave; + _processShot = processShot; + saveScreenshotCheckbox.Checked = true; - if (_screenshotForm != null && _screenshotManager != null) - { - if (_screenshotForm is DockableForm dockableForm && dockableForm.DockState != DockState.Floating) - { - // If this dockable window isn't a floating window, then caller meant to screenshot the Skyline window - var parent = _screenshotForm.ParentForm; - if (parent != null) - { - _screenshotForm = parent; - } - } - // Show the copy buttons - btnCopyToClipBoard.Visible = btnCopyToClipBoard.Enabled = true; - if ((_screenshotForm is GraphSummary zgControl) && zgControl.GraphControl != null) - { - btnCopyMetafileToClipboard.Visible = btnCopyMetafileToClipboard.Enabled = true; // Control is a metafile provider - } - } _linkUrl = link; if (!string.IsNullOrEmpty(link)) { @@ -96,10 +87,17 @@ public PauseAndContinueForm(string description = null, string link = null, bool // Finally make sure the button is fully visible Height += Math.Max(0, (btnContinue.Bottom + btnContinue.Left) - ClientRectangle.Bottom); + + UpdateScreenshotButtonLabels(); } private void btnContinue_Click(object sender, EventArgs e) { + if (screenshotPreviewForm.Visible) + { + screenshotPreviewForm.Hide(); + } + Close(); // Start the tests again @@ -116,7 +114,8 @@ protected override bool ShowWithoutActivation private static readonly object _pauseLock = new object(); - public static void Show(string description = null, string link = null, bool showMatchingPages = false, int? timeout = null, Form screenshotForm = null, ScreenshotManager screenshotManager = null) + public static void Show(string description = null, string fileToSave = null, string link = null, bool showMatchingPages = false, int? timeout = null, + Control screenshotForm = null, bool fullScreen = false, ScreenshotManager screenshotManager = null, Func processShot = null) { ClipboardEx.UseInternalClipboard(false); @@ -128,7 +127,8 @@ public static void Show(string description = null, string link = null, bool show RunUI(parentWindow, () => { - var dlg = new PauseAndContinueForm(description, link, showMatchingPages, screenshotForm, screenshotManager) { Left = parentWindow.Left }; + var dlg = new PauseAndContinueForm(description, fileToSave, link, showMatchingPages, + screenshotForm, fullScreen, screenshotManager, processShot) { Left = parentWindow.Left }; const int spacing = 15; var screen = Screen.FromControl(parentWindow); if (parentWindow.Top > screen.WorkingArea.Top + dlg.Height + spacing) @@ -217,20 +217,60 @@ public void GotoLink() [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); - private void btnCopyToClipboard_Click(object sender, EventArgs e) + private async void btnScreenshot_Click(object sender, EventArgs e) + { + await CaptureScreenShot(saveScreenshotCheckbox.Checked); + } + + private void btnScreenshotAndContinue_Click(object sender, EventArgs e) + { + btnScreenshot_Click(sender, e); + btnContinue_Click(sender, e); + } + private async void btnPreview_Click(object sender, EventArgs e) + { + await CaptureScreenShot(false, true); + } + + private async Task CaptureScreenShot(bool save, bool showPreview = false) { - // Copy current window image to clipboard, with clean edges - _screenshotForm.Focus(); - _screenshotManager.TakeNextShot(_screenshotForm); + ActivateScreenshotForm(); + + await Task.Delay(200); + + var screenshot = _screenshotManager.TakeShot(_screenshotForm, _fullScreen, save ? _fileToSave: null, _processShot); + + if (showPreview) + { + var existingImageBytes = File.ReadAllBytes(_fileToSave); + var existingImageMemoryStream = new MemoryStream(existingImageBytes); + screenshotPreviewForm.ShowScreenshotPreview(screenshot, new Bitmap(existingImageMemoryStream)); + } } - private void btnCopyMetaFileToClipboard_Click(object sender, EventArgs e) + private void ActivateScreenshotForm() { - _screenshotForm.Focus(); - if (_screenshotForm is GraphSummary zgControl) + // If it is a form, try not to change the focus within the form. + var form = (_screenshotForm as Form)?.ParentForm; + if (form != null) { - CopyEmfToolStripMenuItem.CopyEmf(zgControl.GraphControl); + form.Activate(); } + else + { + _screenshotForm.Focus(); + } + } + + private void saveScreenshotCheckbox_CheckedChanged(object sender, EventArgs e) + { + UpdateScreenshotButtonLabels(); + } + + private void UpdateScreenshotButtonLabels() + { + btnScreenshot.Text = saveScreenshotCheckbox.Checked ? "Save Screenshot" : "Take Screenshot"; + btnScreenshotAndContinue.Text = saveScreenshotCheckbox.Checked ? "Save and Continue" : "Take and Continue"; } } } diff --git a/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.resx b/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.resx index 862b8a070d..ca64ac8090 100644 --- a/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.resx +++ b/pwiz_tools/Skyline/TestUtil/PauseAndContinueForm.resx @@ -120,7 +120,7 @@ 17, 17 - + Copies window image to clipboard, and tries to clean up image border by setting all edge pixels to the color most used in the original edge pixels. This may not work well for all system settings, if so you will need to reposition the image so that it is over an empty background (e.g. MSPaint) and use Alt-PrtScn instead. diff --git a/pwiz_tools/Skyline/TestUtil/ScreenshotManager.cs b/pwiz_tools/Skyline/TestUtil/ScreenshotManager.cs index 92cb334de5..6324251360 100644 --- a/pwiz_tools/Skyline/TestUtil/ScreenshotManager.cs +++ b/pwiz_tools/Skyline/TestUtil/ScreenshotManager.cs @@ -4,37 +4,26 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; -using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; -using System.Xml; using DigitalRune.Windows.Docking; using JetBrains.Annotations; -using Microsoft.VisualStudio.TestTools.UnitTesting; using pwiz.Skyline; +using ZedGraph; namespace pwiz.SkylineTestUtil { public class ScreenshotManager { - protected const string ROOT_ELEMENT = "shot_list"; - - private List _shotSequence = new List(); -// private ShotType _defaultShotType = ShotType.ActiveWindow; private SkylineWindow _skylineWindow; - private int _currentShotIndex; - private TestContext _ctx; - private XmlDocument _storage; - public class PointFactor { private float _factor; public PointFactor(float pFactor) { _factor = pFactor; } - - public float getFloat() { return _factor; } + public static Point operator *(Point pt, PointFactor pFactor) => new Point((int)Math.Round(pt.X * pFactor._factor), (int)Math.Round(pt.Y * pFactor._factor)); public static Size operator *(Size sz, PointFactor pFactor) => new Size((int)Math.Round(sz.Width * pFactor._factor), (int)Math.Round(sz.Height * pFactor._factor)); public static Rectangle operator *(Rectangle rect, PointFactor pFactor) => new Rectangle(rect.Location * pFactor, rect.Size * pFactor); @@ -50,125 +39,103 @@ public class PointAdditive public static implicit operator Point(PointAdditive add) => add._add; } - public enum ShotType{ ActiveWindow, SkylineWindow, SkylineCustomArea} - private abstract class SkylineScreenshot + public static Rectangle GetWindowRectangle(Control ctrl, bool fullScreen = false) { -// private readonly ShotType _type; -// private readonly SkylineWindow _skylineWindow; - - protected const string SHOT_ELEMENT = "shot"; - protected const string SHOT_TYPE_ATTRIBUTE = "type"; - protected const string SHOT_TYPE_VAL_ACTIVE_FORM = "active_form"; - protected const string SHOT_TYPE_VAL_CUSTOM_AREA = "skyline_relative_frame"; - protected const string SHOT_FRAME_ELEMENT = "frame"; - protected const string SHOT_FRAME_LEFT_ATTRIBUTE = "left"; - protected const string SHOT_FRAME_TOP_ATTRIBUTE = "top"; - protected const string SHOT_FRAME_RIGHT_ATTRIBUTE = "right"; - protected const string SHOT_FRAME_BOTTOM_ATTRIBUTE = "bottom"; - - - [DllImport("gdi32.dll")] - static extern int GetDeviceCaps(IntPtr hdc, int nIndex); - [DllImport("user32.dll")] - private static extern IntPtr GetForegroundWindow(); - - public enum DeviceCap + var snapshotBounds = Rectangle.Empty; + + var dockedStates = new[] { DockState.DockBottom, DockState.DockLeft, DockState.DockRight, DockState.DockTop, DockState.Document }; + var form = ctrl as DockableForm; + if (form != null && dockedStates.Any((state) => form.DockState == state)) { - VERTRES = 10, - DESKTOPVERTRES = 117, + Point origin = Point.Empty; + ctrl.Invoke(new Action(() => { origin = form.Pane.PointToScreen(new Point(0, 0)); })); + snapshotBounds = new Rectangle(origin, form.Pane.Size); } - - /** - * Factory method - */ - public static SkylineScreenshot CreateScreenshot(SkylineWindow pSkylineWindow, [NotNull] XmlNode shotNode) + else if (fullScreen) { - // ReSharper disable PossibleNullReferenceException - if (shotNode.Attributes[SHOT_TYPE_ATTRIBUTE] == null) - throw new InvalidDataException("Invalid XML. type attribute was expected but was not found."); - - if (shotNode.Attributes[SHOT_TYPE_ATTRIBUTE].Value == SHOT_TYPE_VAL_ACTIVE_FORM) - return new ActiveWindowShot(pSkylineWindow, shotNode); - else if (shotNode.Attributes[SHOT_TYPE_ATTRIBUTE].Value == SHOT_TYPE_VAL_CUSTOM_AREA) - return new CustomAreaShot(pSkylineWindow, shotNode); - else throw new InvalidDataException("Unsupported screenshot type"); - // ReSharper restore PossibleNullReferenceException + snapshotBounds = Screen.FromControl(ctrl).Bounds; } - - public SkylineScreenshot(ShotType pShotType, SkylineWindow pSkylineWindow) + else { -// _type = pShotType; -// _skylineWindow = pSkylineWindow; + ctrl = FindParent(ctrl) ?? ctrl; + int width = (ctrl as Form)?.DesktopBounds.Width ?? ctrl.Width; + int frameWidth = (width - ctrl.ClientRectangle.Width) / 2 - SystemInformation.Border3DSize.Width + SystemInformation.BorderSize.Width; + Size imageSize = ctrl.Size + new PointAdditive(-2 * frameWidth, -frameWidth); + Point sourcePoint = ctrl.Location + new PointAdditive(frameWidth, 0); + snapshotBounds = new Rectangle(sourcePoint, imageSize); } + return snapshotBounds * GetScalingFactor(); + } - protected PointFactor GetScalingFactor() + public static Control FindParent(Control ctrl) + { + while (ctrl != null) { - Graphics g = Graphics.FromHwnd(IntPtr.Zero); - IntPtr desktop = g.GetHdc(); - int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES); - int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); + if (ctrl is TParent) + return ctrl; + ctrl = ctrl.Parent; + } - float ScreenScalingFactor = PhysicalScreenHeight / (float)LogicalScreenHeight; + return null; + } - return new PointFactor(ScreenScalingFactor); // 1.25 = 125% - } + [DllImport("gdi32.dll")] + static extern int GetDeviceCaps(IntPtr hdc, int nIndex); + private enum DeviceCap + { + VERTRES = 10, + DESKTOPVERTRES = 117, + } - protected Rectangle GetWindowRectangle(Form frm) - { - Rectangle snapshotBounds = Rectangle.Empty; + public static PointFactor GetScalingFactor() + { + Graphics g = Graphics.FromHwnd(IntPtr.Zero); + IntPtr desktop = g.GetHdc(); + int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES); + int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); + + float ScreenScalingFactor = PhysicalScreenHeight / (float)LogicalScreenHeight; - DockState[] dockedStates = new DockState[]{DockState.DockBottom, DockState.DockLeft, DockState.DockBottom, DockState.DockTop, DockState.Document}; - if (frm is DockableForm && dockedStates.Any((state) => ((frm as DockableForm)?.DockState == state) ) ) + return new PointFactor(ScreenScalingFactor); // 1.25 = 125% + } + private abstract class SkylineScreenshot + { + /** + * Factory method + */ + public static SkylineScreenshot CreateScreenshot(Control control, bool fullScreen = false) + { + SkylineScreenshot newShot; + if (control is ZedGraphControl zedGraphControl) { - Point origin = Point.Empty; - frm.Invoke(new Action(() => { origin = frm.PointToScreen(new Point(0, 0)); })); - PointAdditive frameOffset = new PointAdditive(-((frm as DockableForm).Pane.Width - frm.Width) / 2, - -((frm as DockableForm).Pane.Height - frm.Height)); - snapshotBounds = new Rectangle(origin + frameOffset, (frm as DockableForm).Pane.Size); + newShot = new ZedGraphShot(zedGraphControl); } else { - if (frm.ParentForm is FloatingWindow) - frm = frm.ParentForm; - int frameWidth = (frm.DesktopBounds.Width - frm.ClientRectangle.Width) / 2 - SystemInformation.Border3DSize.Width + SystemInformation.BorderSize.Width; - Size imageSize = frm.Size + new PointAdditive(-2 * frameWidth, -frameWidth); - Point sourcePoint = frm.Location + new PointAdditive(frameWidth, 0); - snapshotBounds = new Rectangle(sourcePoint, imageSize); - + newShot = new ActiveWindowShot(control, fullScreen); } - return snapshotBounds * GetScalingFactor(); - } - /** - * Incapsulates UI actions required to configure the screenshot. In the case of CustomAreaShot it should - * show the framing window and take its coordinates. Nothing to be done for an ActiveWindowShot. - */ - public abstract void SetUp(); - public abstract Bitmap Take(Form activeWindow); - public abstract XmlNode Serialize(XmlDocument pDoc); + return newShot; + } + public abstract Bitmap Take(); } private class ActiveWindowShot : SkylineScreenshot { - public ActiveWindowShot(SkylineWindow pSkylineWindow, XmlNode pNode) : - base(ShotType.ActiveWindow, pSkylineWindow) - { - - } - public ActiveWindowShot(SkylineWindow pSkylineWindow) : - base(ShotType.ActiveWindow, pSkylineWindow) + private readonly Control _activeWindow; + private readonly bool _fullscreen; + public ActiveWindowShot(Control activeWindow, bool fullscreen) { - + _activeWindow = activeWindow; + _fullscreen = fullscreen; } - public override void SetUp() {} - [NotNull] - public override Bitmap Take(Form activeWindow) + public override Bitmap Take() { - Rectangle shotFrame = GetWindowRectangle(activeWindow); + Rectangle shotFrame = GetWindowRectangle(_activeWindow, _fullscreen); Bitmap bmCapture = new Bitmap(shotFrame.Width, shotFrame.Height, PixelFormat.Format32bppArgb); Graphics graphCapture = Graphics.FromImage(bmCapture); bool captured = false; @@ -188,161 +155,63 @@ public override Bitmap Take(Form activeWindow) graphCapture.Dispose(); return bmCapture; } - - [NotNull] - public override XmlNode Serialize(XmlDocument pDoc) - { - // ReSharper disable PossibleNullReferenceException - XmlNode node = pDoc.CreateElement(SHOT_ELEMENT); - XmlAttribute typeAttr = pDoc.CreateAttribute(SHOT_TYPE_ATTRIBUTE); - typeAttr.Value = SHOT_TYPE_VAL_ACTIVE_FORM; - node.Attributes.Append(typeAttr); - pDoc.DocumentElement.AppendChild(node); - return node; - // ReSharper restore PossibleNullReferenceException - } - } - private class CustomAreaShot : SkylineScreenshot + private class ZedGraphShot : SkylineScreenshot { - private Rectangle _shotFrame; - public CustomAreaShot(SkylineWindow pSkylineWindow, [NotNull] XmlNode pNode) : base(ShotType.ActiveWindow, pSkylineWindow) - { - if (pNode.FirstChild != null && pNode.FirstChild.LocalName == SHOT_FRAME_ELEMENT) - { - XmlAttributeCollection rAtts = pNode.FirstChild.Attributes ?? - throw new NullReferenceException( - nameof(pNode.FirstChild.Attributes)); - _shotFrame = new Rectangle(Int16.Parse(rAtts[SHOT_FRAME_LEFT_ATTRIBUTE].Value), - Int16.Parse(rAtts[SHOT_FRAME_TOP_ATTRIBUTE].Value), - Int16.Parse(rAtts[SHOT_FRAME_RIGHT_ATTRIBUTE].Value), - Int16.Parse(rAtts[SHOT_FRAME_BOTTOM_ATTRIBUTE].Value) - ); - } - else throw new InvalidDataException("Expected frame coordinates for this type of a screenshot, but it was not found."); - } - public CustomAreaShot(SkylineWindow pSkylineWindow) : base(ShotType.SkylineCustomArea, pSkylineWindow) + private readonly ZedGraphControl _zedGraphControl; + public ZedGraphShot(ZedGraphControl zedGraphControl) { - + _zedGraphControl = zedGraphControl; } - - [NotNull] - public override XmlNode Serialize(XmlDocument pDoc) + public override Bitmap Take() { - throw new NotImplementedException(); - } - - /** - * Display the snapshot area selector and return the resulting rectangle - * in display coordinates. - */ - public Rectangle ShowAreaSelector() - { - throw new NotImplementedException(); - } - - public override void SetUp() - { - } - - public override Bitmap Take(Form activeWindow) - { - Bitmap bmCapture = new Bitmap(_shotFrame.Width, _shotFrame.Height, PixelFormat.Format32bppArgb); - Graphics graphCapture = Graphics.FromImage(bmCapture); - graphCapture.CopyFromScreen(_shotFrame.Location, - new Point(0, 0), _shotFrame.Size); - graphCapture.Dispose(); - return bmCapture; + Metafile emf = (_zedGraphControl.MasterPane.GetMetafile()); + Bitmap bmp = new Bitmap(emf.Width, emf.Height); + bmp.SetResolution(emf.HorizontalResolution, emf.VerticalResolution); + using (Graphics g = Graphics.FromImage(bmp)) + { + g.DrawImage(emf, 0, 0); + } + return bmp; } } - - private string FilePath + public ScreenshotManager([NotNull] SkylineWindow pSkylineWindow) { - get - { - var exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - return Path.Combine(exeDir ?? "", _ctx.TestName + "_shots"); - } + _skylineWindow = pSkylineWindow; } - public ScreenshotManager([NotNull] TestContext ctx, [NotNull] SkylineWindow pSkylineWindow) - { - //look up the settings file, read and parse if found - //set up defaults otherwise - _ctx = ctx; + public Bitmap TakeShot(Control activeWindow, bool fullScreen = false, string pathToSave = null, Func processShot = null, double? scale = null) + { + if (activeWindow == null) + activeWindow = _skylineWindow; + //check UI and create a blank shot according to the user selection + SkylineScreenshot newShot = SkylineScreenshot.CreateScreenshot(activeWindow, fullScreen); - _storage = new XmlDocument(); + Bitmap shotPic = newShot.Take(); + shotPic = processShot != null ? processShot.Invoke(shotPic) : shotPic; + CleanupBorder(shotPic); // Tidy up annoying variations in screenshot border due to underlying windows - if (File.Exists(FilePath)) + if (scale.HasValue) { - _storage.Load(FilePath); - XmlNode root = _storage.DocumentElement; - // ReSharper disable once PossibleNullReferenceException - if (root.HasChildNodes) - { - foreach (XmlNode shotNode in root.ChildNodes) - { - _shotSequence.Add(SkylineScreenshot.CreateScreenshot(pSkylineWindow, shotNode)); - } - } + shotPic = new Bitmap(shotPic, + (int) Math.Round(shotPic.Width * scale.Value), + (int) Math.Round(shotPic.Height * scale.Value)); } - else - _storage.AppendChild(_storage.CreateElement(ROOT_ELEMENT)); - - _currentShotIndex = -1; - } - - public Bitmap TakeNextShot(Form activeWindow, string pathToSave = null, Action processShot = null, double? scale = null) - { - _skylineWindow = Program.MainWindow; - if (activeWindow == null) - activeWindow = _skylineWindow; - Bitmap shotPic; - if ( ++_currentShotIndex < _shotSequence.Count) - { - shotPic = _shotSequence[_currentShotIndex].Take(activeWindow); - } - else + if (pathToSave != null) { - //check UI and create a blank shot according to the user selection - SkylineScreenshot newShot = new ActiveWindowShot(_skylineWindow); - _shotSequence.Add(newShot); - _currentShotIndex = _shotSequence.Count - 1; - shotPic = _shotSequence.Last().Take(activeWindow); - // ReSharper disable once PossibleNullReferenceException - _storage.DocumentElement.AppendChild(newShot.Serialize(_storage)); - SaveToFile(); + SaveToFile(pathToSave, shotPic); } - if (shotPic != null) - { - processShot?.Invoke(shotPic); - CleanupBorder(shotPic); // Tidy up annoying variations in screen shot boarder due to underlying windows - - if (scale.HasValue) - { - shotPic = new Bitmap(shotPic, - (int) Math.Round(shotPic.Width * scale.Value), - (int) Math.Round(shotPic.Height * scale.Value)); - } - if (pathToSave != null) - { - SaveToFile(pathToSave, shotPic); - } - else - { - //Have to do it this way because of the limitation on OLE access from background threads. - Thread clipThread = new Thread(() => Clipboard.SetImage(shotPic)); - clipThread.SetApartmentState(ApartmentState.STA); - clipThread.Start(); - clipThread.Join(); - } - } + //Have to do it this way because of the limitation on OLE access from background threads. + Thread clipThread = new Thread(() => Clipboard.SetImage(shotPic)); + clipThread.SetApartmentState(ApartmentState.STA); + clipThread.Start(); + clipThread.Join(); return shotPic; } @@ -395,7 +264,6 @@ void UpdateStats(int x, int y) private void SaveToFile(string filePath, Bitmap bmp) { - filePath = filePath ?? FilePath; if (File.Exists(filePath)) File.Delete(filePath); var dirPath = Path.GetDirectoryName(filePath); @@ -404,14 +272,6 @@ private void SaveToFile(string filePath, Bitmap bmp) bmp.Save(filePath); } - - private void SaveToFile() - { - if (File.Exists(FilePath)) - File.Delete(FilePath); - - _storage.Save(FilePath); - } } } diff --git a/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.Designer.cs b/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.Designer.cs new file mode 100644 index 0000000000..89dc71b279 --- /dev/null +++ b/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.Designer.cs @@ -0,0 +1,137 @@ +namespace pwiz.SkylineTestUtil +{ + partial class ScreenshotPreviewForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.newScreenshotPictureBox = new System.Windows.Forms.PictureBox(); + this.oldScreenshotPictureBox = new System.Windows.Forms.PictureBox(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.newScreenshotLabel = new System.Windows.Forms.Label(); + this.oldScreenshotLabel = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.newScreenshotPictureBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.oldScreenshotPictureBox)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // newScreenshotPictureBox + // + this.newScreenshotPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.newScreenshotPictureBox.Location = new System.Drawing.Point(0, 0); + this.newScreenshotPictureBox.Name = "newScreenshotPictureBox"; + this.newScreenshotPictureBox.Size = new System.Drawing.Size(308, 226); + this.newScreenshotPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.newScreenshotPictureBox.TabIndex = 0; + this.newScreenshotPictureBox.TabStop = false; + // + // oldScreenshotPictureBox + // + this.oldScreenshotPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.oldScreenshotPictureBox.Location = new System.Drawing.Point(0, 0); + this.oldScreenshotPictureBox.Name = "oldScreenshotPictureBox"; + this.oldScreenshotPictureBox.Size = new System.Drawing.Size(328, 226); + this.oldScreenshotPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.oldScreenshotPictureBox.TabIndex = 1; + this.oldScreenshotPictureBox.TabStop = false; + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.IsSplitterFixed = true; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.newScreenshotLabel); + this.splitContainer1.Panel1.Controls.Add(this.newScreenshotPictureBox); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.oldScreenshotLabel); + this.splitContainer1.Panel2.Controls.Add(this.oldScreenshotPictureBox); + this.splitContainer1.Size = new System.Drawing.Size(637, 226); + this.splitContainer1.SplitterDistance = 308; + this.splitContainer1.SplitterWidth = 1; + this.splitContainer1.TabIndex = 2; + // + // newScreenshotLabel + // + this.newScreenshotLabel.AutoSize = true; + this.newScreenshotLabel.BackColor = System.Drawing.SystemColors.ActiveCaptionText; + this.newScreenshotLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 14F); + this.newScreenshotLabel.ForeColor = System.Drawing.SystemColors.Window; + this.newScreenshotLabel.Location = new System.Drawing.Point(13, 13); + this.newScreenshotLabel.Name = "newScreenshotLabel"; + this.newScreenshotLabel.Size = new System.Drawing.Size(221, 32); + this.newScreenshotLabel.TabIndex = 1; + this.newScreenshotLabel.Text = "New Screenshot"; + // + // oldScreenshotLabel + // + this.oldScreenshotLabel.AutoSize = true; + this.oldScreenshotLabel.BackColor = System.Drawing.SystemColors.ActiveCaptionText; + this.oldScreenshotLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 14F); + this.oldScreenshotLabel.ForeColor = System.Drawing.SystemColors.Window; + this.oldScreenshotLabel.Location = new System.Drawing.Point(13, 13); + this.oldScreenshotLabel.Name = "oldScreenshotLabel"; + this.oldScreenshotLabel.Size = new System.Drawing.Size(210, 32); + this.oldScreenshotLabel.TabIndex = 2; + this.oldScreenshotLabel.Text = "Old Screenshot"; + // + // ScreenshotPreviewForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(637, 226); + this.Controls.Add(this.splitContainer1); + this.Name = "ScreenshotPreviewForm"; + this.Text = "ScreenshotPreviewForm"; + ((System.ComponentModel.ISupportInitialize)(this.newScreenshotPictureBox)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.oldScreenshotPictureBox)).EndInit(); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + this.splitContainer1.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox newScreenshotPictureBox; + private System.Windows.Forms.PictureBox oldScreenshotPictureBox; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.Label newScreenshotLabel; + private System.Windows.Forms.Label oldScreenshotLabel; + } +} \ No newline at end of file diff --git a/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.cs b/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.cs new file mode 100644 index 0000000000..c0c3e60a94 --- /dev/null +++ b/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.cs @@ -0,0 +1,68 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace pwiz.SkylineTestUtil +{ + public partial class ScreenshotPreviewForm : Form + { + private static readonly int SCREENSHOT_MAX_WIDTH = 800; //doubled as side by side + private static readonly int SCREENSHOT_MAX_HEIGHT = 800; + + public ScreenshotPreviewForm() + { + InitializeComponent(); + } + + + public void ShowScreenshotPreview(Bitmap newScreenshot, Bitmap oldScreenShot) + { + var newScreenshotSize = CalculateBitmapSize(newScreenshot); + var oldScreenshotSize = CalculateBitmapSize(oldScreenShot); + var newScreenshotBitmap = new Bitmap(newScreenshot, newScreenshotSize); + var oldScreenshotBitmap = new Bitmap(oldScreenShot, oldScreenshotSize); + SetPreviewImages(newScreenshotBitmap, oldScreenshotBitmap); + this.Show(); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + e.Cancel = true; + this.Hide(); + + base.OnFormClosing(e); + } + + private void SetPreviewImages(Bitmap newScreenshot, Bitmap oldScreenShot) + { + newScreenshotPictureBox.Image = newScreenshot; + oldScreenshotPictureBox.Image = oldScreenShot; + + splitContainer1.SplitterDistance = splitContainer1.Width / 2; + + var minFormWidth = newScreenshot.Width + oldScreenShot.Width; + var minFormHeight = Math.Max(newScreenshot.Height, oldScreenShot.Height); + if (ClientSize.Width < minFormWidth || ClientSize.Height < minFormHeight) + { + ClientSize = new Size(minFormWidth, minFormHeight); + } + + } + + private Size CalculateBitmapSize(Bitmap bitmap) + { + var startingSize = bitmap.Size; + var scaledHeight = (double)SCREENSHOT_MAX_HEIGHT / startingSize.Height; + var scaledWidth = (double)SCREENSHOT_MAX_WIDTH / startingSize.Width; + + //If constraints are not breached then use existing size + if (scaledHeight >= 1 && scaledWidth >= 1) + { + return startingSize; + } + + var scale = Math.Min(scaledHeight, scaledWidth); + return new Size((int)(startingSize.Width * scale), (int)(startingSize.Height * scale)); + } + } +} diff --git a/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.resx b/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/pwiz_tools/Skyline/TestUtil/TestFunctional.cs b/pwiz_tools/Skyline/TestUtil/TestFunctional.cs index 0f4717ef60..38bef23d52 100644 --- a/pwiz_tools/Skyline/TestUtil/TestFunctional.cs +++ b/pwiz_tools/Skyline/TestUtil/TestFunctional.cs @@ -30,6 +30,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; +using DigitalRune.Windows.Docking; using Excel; using JetBrains.Annotations; // using Microsoft.Diagnostics.Runtime; only needed for stack dump logic, which is currently disabled @@ -52,7 +53,6 @@ using pwiz.Skyline.Model; using pwiz.Skyline.Model.AuditLog; using pwiz.Skyline.Model.DocSettings; -using pwiz.Skyline.Model.DocSettings.AbsoluteQuantification; using pwiz.Skyline.Model.Find; using pwiz.Skyline.Model.Lib.BlibData; using pwiz.Skyline.Model.Proteome; @@ -63,6 +63,8 @@ using pwiz.Skyline.Util; using pwiz.Skyline.Util.Extensions; using TestRunnerLib; +using ZedGraph; +using SampleType = pwiz.Skyline.Model.DocSettings.AbsoluteQuantification.SampleType; namespace pwiz.SkylineTestUtil { @@ -692,6 +694,8 @@ public static T GetUIValue(Func act) return result; } + private static FormLookup _formLookup; + public static TDlg TryWaitForOpenForm(int millis = WAIT_TIME, Func stopCondition = null) where TDlg : Form { int waitCycles = GetWaitCycles(millis); @@ -715,8 +719,7 @@ public static TDlg TryWaitForOpenForm(int millis = WAIT_TIME, Func s }); } - if (_formLookup == null) - _formLookup = new FormLookup(); + _formLookup ??= new FormLookup(); Assert.IsNotNull(_formLookup.GetTest(formType), formType + " must be added to TestRunnerLib\\TestRunnerFormLookup.csv"); @@ -761,8 +764,7 @@ public static Form TryWaitForOpenForm(Type formType, int millis = WAIT_TIME, Fun }); } - if (_formLookup == null) - _formLookup = new FormLookup(); + _formLookup ??= new FormLookup(); Assert.IsNotNull(_formLookup.GetTest(formTypeName), formType + " must be added to TestRunnerLib\\TestRunnerFormLookup.csv"); @@ -1224,6 +1226,21 @@ public bool IsCoverShotMode } } + private static bool _isAutoScreenShotMode; + + public bool IsAutoScreenShotMode + { + get { return _isAutoScreenShotMode || Program.PauseSeconds == -3; } // -3 is the magic number SkylineTester uses to indicate cover shot mode + set + { + _isAutoScreenShotMode = value; + if (_isAutoScreenShotMode) + { + Program.PauseSeconds = -3; // -3 is the magic number SkylineTester uses to indicate cover shot mode + } + } + } + public string CoverShotName { get; set; } private string GetCoverShotPath(string folderPath = null, string suffix = null) @@ -1254,6 +1271,18 @@ private bool IsTutorial get { return TestContext.TestName.Contains("Tutorial"); } } + private string TutorialPath + { + get { return IsTutorial ? + TestContext.GetProjectDirectory($"Documentation\\Tutorials\\{CoverShotName}\\{CultureInfo.CurrentCulture.TwoLetterISOLanguageName}") + : null; + } + } + + private int ScreenShotCounter = 1; + + protected virtual int[] NonScreenShotFigures => Array.Empty(); + public virtual bool AuditLogCompareLogs { get { return IsTutorial && !IsFullData; } // Logs were recorded with partial data and not in Pass0 @@ -1281,31 +1310,110 @@ public bool IsRecordAuditLogForTutorials private string LinkPage(int? pageNum) { - return pageNum.HasValue ? LinkPdf + "#page=" + pageNum : null; + if (string.IsNullOrEmpty(TutorialPath)) + return null; + int figureNum = ScreenShotCounter + NonScreenShotFigures.Count(n => n <= ScreenShotCounter); + var fileUri = new Uri(Path.Combine(TutorialPath, "index.html")).AbsoluteUri + "#figure" + figureNum; + const string tutorialSearch = "/Tutorials/"; + int tutorialIndex = fileUri.IndexOf(tutorialSearch, StringComparison.Ordinal); + return "https://skyline.ms/tutorials/24-1/" + fileUri.Substring(tutorialIndex + tutorialSearch.Length); } - private static FormLookup _formLookup; + protected Bitmap ClipSkylineWindowShotWithForms(Bitmap skylineWindowBmp, IList dockableForms) + { + return ClipBitmap(skylineWindowBmp, ComputeDockableFormInclusiveRectangle(dockableForms)); + } + + private Rectangle ComputeDockableFormInclusiveRectangle(IList dockableForms) + { + return dockableForms + .Select(ComputeDockableFormScreenRectangle) + .Aggregate(Rectangle.Union); + } - public void PauseForScreenShot(string description = null, int? pageNum = null, int? timeout = null) + private Rectangle ComputeDockableFormScreenRectangle(DockableForm dockableForm) { - PauseForScreenShot(description, pageNum, null, null, timeout); + var formRectangle = ScreenshotManager.GetWindowRectangle(dockableForm); + var skylineWindowPoint = new Point(SkylineWindow.Location.X, SkylineWindow.Location.Y) * ScreenshotManager.GetScalingFactor(); + var skylineRelativeOrigin = new Point(formRectangle.X - skylineWindowPoint.X, formRectangle.Y - skylineWindowPoint.Y); + return new Rectangle(skylineRelativeOrigin, formRectangle.Size); } - public void PauseForScreenShot(Form screenshotForm, string description = null, int? pageNum = null, int? timeout = null) + + protected Bitmap ClipSelectionStatus(Bitmap skylineWindowBmp) + { + int clipWidth = SkylineWindow.StatusSelectionWidth; + int clipHeight = SkylineWindow.StatusBarHeight; + var cropRect = new Rectangle(skylineWindowBmp.Width - clipWidth, skylineWindowBmp.Height - clipHeight, clipWidth, clipHeight); + return ClipBitmap(skylineWindowBmp, cropRect); + } + + protected static Bitmap ClipBitmap(Image bmp, Rectangle rect) + { + var croppedShot = new Bitmap(rect.Width, rect.Height); + using var g = Graphics.FromImage(croppedShot); + + g.DrawImage(bmp, new Rectangle(0, 0, rect.Width, rect.Height), rect, GraphicsUnit.Pixel); + + return croppedShot; + } + + protected GraphSummary FindGraphSummaryByGraphType() where TGraphPane : SummaryGraphPane + { + return FormUtil.OpenForms.OfType() + .FirstOrDefault(graphSummary => graphSummary.TryGetGraphPane(out TGraphPane _)); + } + + public void PauseForScreenShot(string description = null, int? pageNum = null, int? timeout = null, Func processShot = null) + { + PauseForScreenShot(description, pageNum, null, null, timeout, processShot); + } + public void PauseForScreenShot(Control screenshotForm, string description = null, int? pageNum = null, int ? timeout = null) { PauseForScreenShot(description, pageNum, null, screenshotForm, timeout); } - public void PauseForScreenShot(string description, int? pageNum = null, int? timeout = null) + public void PauseForScreenShot(string description, int? pageNum = null, int ? timeout = null, Func processShot = null) where TView : IFormView { - PauseForScreenShot(description, pageNum, typeof(TView), null, timeout); + PauseForScreenShot(description, pageNum, typeof(TView), null, timeout, processShot); + } + + public void PauseForGraphScreenShot(string description, Control graphContainer, int? pageNum = null, int? timeout = null) + { + var zedGraph = FindZedGraph(graphContainer); + Assert.IsNotNull(zedGraph, "Control was not or did not contain a graph."); + PauseForScreenShot(description, pageNum, null, zedGraph, timeout); } - private void PauseForScreenShot(string description, int? pageNum, Type formType, Form screenshotForm = null, int? timeout = null) + private ZedGraphControl FindZedGraph(Control graphContainer) { + var zedGraphControl = graphContainer as ZedGraphControl; + if (zedGraphControl != null) + return zedGraphControl; + foreach (Control childControl in graphContainer.Controls) + { + zedGraphControl = FindZedGraph(childControl); + if (zedGraphControl != null) + return zedGraphControl; + } + + return null; + } + + /// + /// Type that indicates a full-screen screenshot should be taken + /// + public class ScreenForm : IFormView + { + } + + private void PauseForScreenShot(string description, int? pageNum, Type formType = null, Control screenshotForm = null, int? timeout = null, Func processShot = null) + { + bool fullScreen = formType == typeof(ScreenForm); + if (formType != null) { - var form = TryWaitForOpenForm(formType); + var form = !fullScreen ? TryWaitForOpenForm(formType) : SkylineWindow; Assert.IsNotNull(form); } if (Program.SkylineOffscreen) @@ -1315,37 +1423,48 @@ private void PauseForScreenShot(string description, int? pageNum, Type formType, Thread.Sleep(3 * 1000); else if (Program.PauseSeconds > 0) Thread.Sleep(Program.PauseSeconds * 1000); - else if (IsPauseForScreenShots && Math.Max(PauseStartingPage, Program.PauseStartingPage) <= (pageNum ?? int.MaxValue)) + else if ((IsPauseForScreenShots || IsAutoScreenShotMode) && Math.Max(PauseStartingPage, Program.PauseStartingPage) <= (pageNum ?? int.MaxValue)) { if (screenshotForm == null) { - if (formType != null) + if (!fullScreen && formType != null) { - screenshotForm = TryWaitForOpenForm(formType) ?? SkylineWindow; + screenshotForm = TryWaitForOpenForm(formType); } - else - screenshotForm = SkylineWindow; - RunUI(() => screenshotForm?.Update()); - } + screenshotForm ??= SkylineWindow; -// Thread.Sleep(300); -// _shotManager.TakeNextShot(screenshotForm); + RunUI(() => screenshotForm.Update()); + } var formSeen = new FormSeen(); formSeen.Saw(formType); - bool showMatchingPages = IsShowMatchingTutorialPages || Program.ShowMatchingPages; + var fileToSave = !string.IsNullOrEmpty(TutorialPath) ? $"{Path.Combine(TutorialPath, "s-" + ScreenShotCounter)}.png" : null; - PauseAndContinueForm.Show(description + string.Format(" - p. {0}", pageNum), LinkPage(pageNum), showMatchingPages, timeout, screenshotForm, _shotManager); + if (IsAutoScreenShotMode) + { + Thread.Sleep(3000); + screenshotForm.Focus(); + _shotManager.TakeShot(screenshotForm, fullScreen, fileToSave, processShot); + } + else + { + bool showMatchingPages = IsShowMatchingTutorialPages || Program.ShowMatchingPages; + PauseAndContinueForm.Show(description + string.Format(" - fig. {0}", ScreenShotCounter), fileToSave, LinkPage(pageNum), showMatchingPages, timeout, + screenshotForm, fullScreen, _shotManager, processShot); + } } else { PauseForForm(formType); } + + ScreenShotCounter++; } - protected virtual void ProcessCoverShot(Bitmap bmp) + protected virtual Bitmap ProcessCoverShot(Bitmap bmp) { // Override to modify the cover shot before it is saved or put on the clipboard + return bmp; } public void TakeCoverShot() @@ -1358,13 +1477,13 @@ public void TakeCoverShot() "Cover shots must be taken at screen resolution 1920x1080 at scale factor 100% (96DPI)"); }); var coverSavePath = GetCoverShotPath(); - ScreenshotManager.TakeNextShot(SkylineWindow, coverSavePath, ProcessCoverShot); + ScreenshotManager.TakeShot(SkylineWindow, false, coverSavePath, ProcessCoverShot); string coverSavePath2 = null; if (coverSavePath != null) { // Screenshot for the StartPage coverSavePath2 = GetCoverShotPath(TestContext.GetProjectDirectory(@"Resources\StartPage"), "_start"); - ScreenshotManager.TakeNextShot(SkylineWindow, coverSavePath2, ProcessCoverShot, 0.20); + ScreenshotManager.TakeShot(SkylineWindow, false, coverSavePath2, ProcessCoverShot, 0.20); } if (coverSavePath == null) { @@ -1514,7 +1633,7 @@ protected void RunFunctionalTestOrThrow(string defaultUiMode) UnzipTestFiles(); - _shotManager = new ScreenshotManager(TestContext, SkylineWindow); + _shotManager = new ScreenshotManager(SkylineWindow); // Run test in new thread (Skyline on main thread). Program.Init(); diff --git a/pwiz_tools/Skyline/TestUtil/TestUtil.csproj b/pwiz_tools/Skyline/TestUtil/TestUtil.csproj index 210ef8817a..cf4dd2cfe7 100644 --- a/pwiz_tools/Skyline/TestUtil/TestUtil.csproj +++ b/pwiz_tools/Skyline/TestUtil/TestUtil.csproj @@ -150,6 +150,12 @@ + + Form + + + ScreenshotPreviewForm.cs + @@ -231,6 +237,10 @@ PauseAndContinueForm.cs + Designer + + + ScreenshotPreviewForm.cs