diff --git a/docs/guide_run_notes.md b/docs/guide_run_notes.md new file mode 100644 index 0000000..788f311 --- /dev/null +++ b/docs/guide_run_notes.md @@ -0,0 +1,76 @@ +# GUIDE Version Run Notes + +The MATLAB R2022a entry point now launches the GUIDE-compatible UI. GUIDE does not support `uitabgroup` or `uitab`, so this UI uses GUIDE-supported `uipanel` containers plus `popupmenu` selectors to simulate pages. + +Main files: + +- `gui_support/app/EDFMSimulatorGuide.fig` +- `gui_support/app/EDFMSimulatorGuide.m` + +## Run + +In MATLAB R2022a: + +```matlab +cd('C:\Users\15715\Documents\3D_EDFM_SIM-X') +startup +app = launch_edfm_simulator_guide; +``` + +The generic launcher also starts the GUIDE version: + +```matlab +cd('C:\Users\15715\Documents\3D_EDFM_SIM-X') +startup +app = launch_edfm_simulator_app; +``` + +## Edit With GUIDE + +Open the FIG in GUIDE: + +```matlab +guide('C:\Users\15715\Documents\3D_EDFM_SIM-X\gui_support\app\EDFMSimulatorGuide.fig') +``` + +The top-level page selector is `PageDropDown`. Each page is a stacked `uipanel`, such as `ModelTab`, `GridTab`, `FlowTab`, and `ResultsTab`. + +Because the page panels overlap, simply setting one panel to `Visible=on` may still leave another visible panel covering it. The most reliable editing workflow is to open GUIDE through the page helper: + +```matlab +edit_edfm_guide_page('Model') +edit_edfm_guide_page('Flow') +edit_edfm_guide_page('Results') +``` + +For inner pages: + +```matlab +edit_edfm_guide_page('SP') +edit_edfm_guide_page('DP') +edit_edfm_guide_page('GasWater') +edit_edfm_guide_page('OilWater') +edit_edfm_guide_page('MultiComponent') +``` + +This helper updates the same `EDFMSimulatorGuide.fig` file before opening GUIDE: it turns the other panels in the same group off, brings the selected panel to the top, saves the FIG, and then opens GUIDE. Save and close an already-open GUIDE editor before switching pages with this command, otherwise GUIDE may keep an older in-memory copy. + +`show_edfm_guide_page` is lower-level and only works on a normal open figure handle. GUIDE's design window is not always exposed as a normal MATLAB figure, so prefer `edit_edfm_guide_page` for day-to-day editing. + +The Property Inspector title may show `matlab.ui.container.Panel`. That is the object class, not the page name. Check the `Tag` property to confirm whether the selected panel is `ResultsTab`, `FlowTab`, or another page. + +Do not freely rename control `Tag` values. `EDFMSimulatorGuide.m` and `EDFMAppController.m` use these tags to find controls and bind callbacks. + +## Regenerate FIG + +If the FIG is lost or damaged, regenerate it from the layout script: + +```matlab +cd('C:\Users\15715\Documents\3D_EDFM_SIM-X') +startup +build_edfm_guide_fig +``` + +This is only a recovery path. Day-to-day UI maintenance should edit `EDFMSimulatorGuide.fig` in GUIDE. + +Do not change the page containers back to `uitabgroup`. MATLAB can display `uitabgroup` at runtime, but GUIDE deletes it when opening the FIG. diff --git a/gui_support/app/EDFMAppController.m b/gui_support/app/EDFMAppController.m index 0fad940..92fd34d 100644 --- a/gui_support/app/EDFMAppController.m +++ b/gui_support/app/EDFMAppController.m @@ -368,29 +368,24 @@ classdef EDFMAppController < handle gridModel = obj.getNumericDropDownValue('ModelGridModelDropDown', 1); flowModel = obj.getNumericDropDownValue('ModelFlowModelDropDown', 1); - if isprop(obj.App, 'TabGroup3') - if gridModel == 2 && isprop(obj.App, 'DPTab') - obj.App.TabGroup3.SelectedTab = obj.App.DPTab; - elseif isprop(obj.App, 'SPTab') - obj.App.TabGroup3.SelectedTab = obj.App.SPTab; - end + if gridModel == 2 + obj.setPanelSelectorValue('DiscretizationPageDropDown', 'DP'); + obj.showOnlyPanels({'SPTab', 'DPTab'}, 'DPTab'); + else + obj.setPanelSelectorValue('DiscretizationPageDropDown', 'SP'); + obj.showOnlyPanels({'SPTab', 'DPTab'}, 'SPTab'); end - if isprop(obj.App, 'TabGroup2') - switch flowModel - case 1 - if isprop(obj.App, 'GasWaterTab') - obj.App.TabGroup2.SelectedTab = obj.App.GasWaterTab; - end - case 2 - if isprop(obj.App, 'OilWaterTab') - obj.App.TabGroup2.SelectedTab = obj.App.OilWaterTab; - end - otherwise - if isprop(obj.App, 'MultiComponentTab') - obj.App.TabGroup2.SelectedTab = obj.App.MultiComponentTab; - end - end + switch flowModel + case 1 + obj.setPanelSelectorValue('FlowPageDropDown', 'GasWater'); + obj.showOnlyPanels({'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}, 'GasWaterTab'); + case 2 + obj.setPanelSelectorValue('FlowPageDropDown', 'OilWater'); + obj.showOnlyPanels({'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}, 'OilWaterTab'); + otherwise + obj.setPanelSelectorValue('FlowPageDropDown', 'MultiComponent'); + obj.showOnlyPanels({'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}, 'MultiComponentTab'); end obj.setEditableState('InitialCsEditField', flowModel == 3); @@ -839,24 +834,37 @@ classdef EDFMAppController < handle obj.setFlowTabControlsVisible('OilWater', showOilWaterTab); obj.setFlowTabControlsVisible('MultiComponent', showMultiComponentTab); - if isprop(obj.App, 'TabGroup2') - switch flowModel - case 1 - if isprop(obj.App, 'GasWaterTab') - obj.App.TabGroup2.SelectedTab = obj.App.GasWaterTab; - end - case 2 - if isprop(obj.App, 'OilWaterTab') - obj.App.TabGroup2.SelectedTab = obj.App.OilWaterTab; - end - otherwise - if isprop(obj.App, 'MultiComponentTab') - obj.App.TabGroup2.SelectedTab = obj.App.MultiComponentTab; - end - end + switch flowModel + case 1 + obj.setPanelSelectorValue('FlowPageDropDown', 'GasWater'); + obj.showOnlyPanels({'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}, 'GasWaterTab'); + case 2 + obj.setPanelSelectorValue('FlowPageDropDown', 'OilWater'); + obj.showOnlyPanels({'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}, 'OilWaterTab'); + otherwise + obj.setPanelSelectorValue('FlowPageDropDown', 'MultiComponent'); + obj.showOnlyPanels({'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}, 'MultiComponentTab'); end end + function showOnlyPanels(obj, panelNames, visiblePanelName) + for i = 1:numel(panelNames) + isVisible = strcmp(panelNames{i}, visiblePanelName); + obj.setControlVisible(panelNames{i}, isVisible); + end + end + + function setPanelSelectorValue(obj, selectorName, selectedItem) + if ~isprop(obj.App, selectorName) + return; + end + component = obj.App.(selectorName); + if ~any(strcmp(component.Items, selectedItem)) + return; + end + component.Value = selectedItem; + end + function setFlowTabControlsVisible(obj, flowTabName, isVisible) switch flowTabName case 'GasWater' @@ -1727,6 +1735,7 @@ classdef EDFMAppController < handle tableHandle = obj.App.(tableName); tableHandle.ColumnName = columnNames; + tableHandle.ColumnWidth = obj.getColumnWidthsForTable(tableName); tableHandle.RowName = {}; switch tableName case 'Well2Table' @@ -1736,6 +1745,21 @@ classdef EDFMAppController < handle end end + function columnWidths = getColumnWidthsForTable(~, tableName) + switch tableName + case 'Well1Table' + columnWidths = {90, 55, 95, 55, 55, 90}; + case 'FractureWellLocationTable' + columnWidths = {140, 140, 140}; + case 'Well2Table' + columnWidths = {100, 70, 120, 70, 70, 130}; + case 'ScheduleTable' + columnWidths = {100, 120, 100, 150, 80, 80, 80, 80, 80, 100}; + otherwise + columnWidths = 'auto'; + end + end + function columnNames = getColumnNamesForTable(~, tableName) switch tableName case 'Well1Table' diff --git a/gui_support/app/EDFMGuideComponent.m b/gui_support/app/EDFMGuideComponent.m index 3ca33c6..92eb5f9 100644 --- a/gui_support/app/EDFMGuideComponent.m +++ b/gui_support/app/EDFMGuideComponent.m @@ -19,6 +19,7 @@ classdef EDFMGuideComponent < handle Editable Data ColumnName + ColumnWidth RowName ColumnEditable ValueChangedFcn @@ -199,6 +200,14 @@ classdef EDFMGuideComponent < handle set(obj.Handle, 'ColumnName', value); end + function value = get.ColumnWidth(obj) + value = get(obj.Handle, 'ColumnWidth'); + end + + function set.ColumnWidth(obj, value) + set(obj.Handle, 'ColumnWidth', value); + end + function value = get.RowName(obj) value = get(obj.Handle, 'RowName'); end diff --git a/gui_support/app/EDFMSimulatorGuide.fig b/gui_support/app/EDFMSimulatorGuide.fig new file mode 100644 index 0000000..4520c85 Binary files /dev/null and b/gui_support/app/EDFMSimulatorGuide.fig differ diff --git a/gui_support/app/EDFMSimulatorGuide.m b/gui_support/app/EDFMSimulatorGuide.m index ec955a2..b889705 100644 --- a/gui_support/app/EDFMSimulatorGuide.m +++ b/gui_support/app/EDFMSimulatorGuide.m @@ -2,8 +2,9 @@ function varargout = EDFMSimulatorGuide(varargin) %EDFMSIMULATORGUIDE GUIDE-compatible EDFM simulator GUI for MATLAB R2022a. % APP = EDFMSIMULATORGUIDE launches the converted GUIDE/uicontrol version % of the App Designer interface. The UI is built from standard figure, -% uitabgroup, uicontrol, uitable and axes objects so it can be inspected and -% adjusted with GUIDE-era tools in MATLAB R2022a. +% uipanel, uicontrol, uitable and axes objects so it can be inspected and +% adjusted with GUIDE-era tools in MATLAB R2022a. GUIDE does not support +% uitabgroup, so pages are implemented as switchable uipanel containers. if nargin > 0 && ischar(varargin{1}) feval(varargin{:}); @@ -19,6 +20,7 @@ handles.App = app; guidata(fig, handles); configureGuideCallbacks(app, fig); app.Controller.startup(); +set(fig, 'Visible', 'on'); if nargout > 0 varargout{1} = app; @@ -37,6 +39,15 @@ end end function configureGuideCallbacks(app, fig) +if isprop(app, 'PageDropDown') + app.PageDropDown.ValueChangedFcn = @(src, event) onMainPageChanged(fig); +end +if isprop(app, 'DiscretizationPageDropDown') + app.DiscretizationPageDropDown.ValueChangedFcn = @(src, event) onDiscretizationPageChanged(fig); +end +if isprop(app, 'FlowPageDropDown') + app.FlowPageDropDown.ValueChangedFcn = @(src, event) onFlowPageChanged(fig); +end app.NewConfigButton.ButtonPushedFcn = @(src, event) onNewConfig(fig); app.LoadTemplateButton.ButtonPushedFcn = @(src, event) onLoadTemplate(fig); app.ImportConfigButton.ButtonPushedFcn = @(src, event) onImportConfig(fig); @@ -68,6 +79,43 @@ app.FractureWellLocationTable.CellSelectionCallback = @(src, event) onTableSelec app.ScheduleTable.CellSelectionCallback = @(src, event) onTableSelection(fig, 'ScheduleTable', event); end +function onMainPageChanged(fig) +handles = guidata(fig); +pageTags = {'ModelTab', 'GridTab', 'FractureTab', 'DiscretizationTab', ... + 'FlowTab', 'WellsTab', 'SolverRunTab', 'ResultsTab'}; +showSelectedPanel(handles, 'PageDropDown', pageTags); +guidata(fig, handles); +end + +function onDiscretizationPageChanged(fig) +handles = guidata(fig); +showSelectedPanel(handles, 'DiscretizationPageDropDown', {'SPTab', 'DPTab'}); +guidata(fig, handles); +end + +function onFlowPageChanged(fig) +handles = guidata(fig); +showSelectedPanel(handles, 'FlowPageDropDown', {'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'}); +guidata(fig, handles); +end + +function showSelectedPanel(handles, selectorName, panelTags) +if ~isfield(handles, selectorName) + return; +end +selectedIndex = get(handles.(selectorName), 'Value'); +selectedIndex = min(max(1, selectedIndex), numel(panelTags)); +for i = 1:numel(panelTags) + if isfield(handles, panelTags{i}) && isgraphics(handles.(panelTags{i})) + if i == selectedIndex + set(handles.(panelTags{i}), 'Visible', 'on'); + else + set(handles.(panelTags{i}), 'Visible', 'off'); + end + end +end +end + function app = getGuideApp(fig) handles = guidata(fig); app = handles.App; diff --git a/gui_support/app/createEDFMSimulatorGuideLayout.m b/gui_support/app/createEDFMSimulatorGuideLayout.m index 490ca01..7eaa15d 100644 --- a/gui_support/app/createEDFMSimulatorGuideLayout.m +++ b/gui_support/app/createEDFMSimulatorGuideLayout.m @@ -33,9 +33,14 @@ handles.ExportResultButton = uicontrol('Parent', fig, 'Style', 'pushbutton', 'Un handles.StatusLabel = uicontrol('Parent', fig, 'Style', 'text', 'Units', 'pixels', 'Position', [984 774 251 22], ... 'String', 'Status', 'HorizontalAlignment', 'left', 'Tag', 'StatusLabel'); -handles.TabGroup = uitabgroup('Parent', fig, 'Units', 'pixels', 'Position', [8 46 1247 706], 'Tag', 'TabGroup'); +handles.PageDropDown = uicontrol('Parent', fig, 'Style', 'popupmenu', 'Units', 'pixels', 'Position', [8 748 170 22], ... + 'String', {'Model', 'Grid', 'Fracture', 'Discretization', 'Flow', 'Wells', 'Solver&Run', 'Results'}, 'Value', 1, 'Tag', 'PageDropDown'); -handles.ModelTab = uitab('Parent', handles.TabGroup, 'Title', 'Model', 'Tag', 'ModelTab'); +handles.TabGroup = uipanel('Parent', fig, 'Units', 'pixels', 'Position', [8 46 1247 698], ... + 'BorderType', 'none', 'Tag', 'TabGroup'); + +handles.ModelTab = uipanel('Parent', handles.TabGroup, 'Title', 'Model', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'ModelTab', 'Visible', 'on'); handles.GridModelDropDownLabel = uicontrol('Parent', handles.ModelTab, 'Style', 'text', 'Units', 'pixels', 'Position', [62 630 60 22], ... 'String', 'GridModel', 'HorizontalAlignment', 'right', 'Tag', 'GridModelDropDownLabel'); @@ -51,7 +56,8 @@ handles.ModelFlowModelDropDown = uicontrol('Parent', handles.ModelTab, 'Style', 'String', {'1', '2', '3'}, 'Value', 1, 'Tag', 'ModelFlowModelDropDown'); setPopupDefaultValue(handles.ModelFlowModelDropDown, '1'); -handles.GridTab = uitab('Parent', handles.TabGroup, 'Title', 'Grid', 'Tag', 'GridTab'); +handles.GridTab = uipanel('Parent', handles.TabGroup, 'Title', 'Grid', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'GridTab', 'Visible', 'off'); handles.DxTextAreaLabel = uicontrol('Parent', handles.GridTab, 'Style', 'text', 'Units', 'pixels', 'Position', [49 643 25 22], ... 'String', 'Dx', 'HorizontalAlignment', 'right', 'Tag', 'DxTextAreaLabel'); @@ -77,7 +83,8 @@ handles.NTGTextAreaLabel = uicontrol('Parent', handles.GridTab, 'Style', 'text', handles.GridNTGTextArea = uicontrol('Parent', handles.GridTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [93 147 267 108], ... 'Max', 2, 'Min', 0, 'HorizontalAlignment', 'left', 'String', '', 'Tag', 'GridNTGTextArea'); -handles.FractureTab = uitab('Parent', handles.TabGroup, 'Title', 'Fracture', 'Tag', 'FractureTab'); +handles.FractureTab = uipanel('Parent', handles.TabGroup, 'Title', 'Fracture', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'FractureTab', 'Visible', 'off'); handles.FractureInputTextAreaLabel = uicontrol('Parent', handles.FractureTab, 'Style', 'text', 'Units', 'pixels', 'Position', [59 571 76 22], ... 'String', 'FractureInput', 'HorizontalAlignment', 'right', 'Tag', 'FractureInputTextAreaLabel'); @@ -85,11 +92,17 @@ handles.FractureInputTextAreaLabel = uicontrol('Parent', handles.FractureTab, 'S handles.FractureInputTextArea = uicontrol('Parent', handles.FractureTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [150 497 241 98], ... 'Max', 2, 'Min', 0, 'HorizontalAlignment', 'left', 'String', '', 'Tag', 'FractureInputTextArea'); -handles.DiscretizationTab = uitab('Parent', handles.TabGroup, 'Title', 'Discretization', 'Tag', 'DiscretizationTab'); +handles.DiscretizationTab = uipanel('Parent', handles.TabGroup, 'Title', 'Discretization', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'DiscretizationTab', 'Visible', 'off'); -handles.TabGroup3 = uitabgroup('Parent', handles.DiscretizationTab, 'Units', 'pixels', 'Position', [48 37 1156 430], 'Tag', 'TabGroup3'); +handles.DiscretizationPageDropDown = uicontrol('Parent', handles.DiscretizationTab, 'Style', 'popupmenu', 'Units', 'pixels', ... + 'Position', [48 480 120 22], 'String', {'SP', 'DP'}, 'Value', 1, 'Tag', 'DiscretizationPageDropDown'); -handles.SPTab = uitab('Parent', handles.TabGroup3, 'Title', 'SP', 'Tag', 'SPTab'); +handles.TabGroup3 = uipanel('Parent', handles.DiscretizationTab, 'Units', 'pixels', 'Position', [48 37 1156 430], ... + 'BorderType', 'none', 'Tag', 'TabGroup3'); + +handles.SPTab = uipanel('Parent', handles.TabGroup3, 'Title', 'SP', 'Units', 'pixels', ... + 'Position', [0 0 1156 430], 'Tag', 'SPTab', 'Visible', 'on'); handles.BoundaryTextAreaLabel = uicontrol('Parent', handles.SPTab, 'Style', 'text', 'Units', 'pixels', 'Position', [30 360 56 22], ... 'String', 'Boundary', 'HorizontalAlignment', 'right', 'Tag', 'BoundaryTextAreaLabel'); @@ -133,7 +146,8 @@ handles.RockDensityEditFieldLabel = uicontrol('Parent', handles.SPTab, 'Style', handles.SPRockDensityEditField = uicontrol('Parent', handles.SPTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [103 165 144 22], ... 'HorizontalAlignment', 'left', 'String', '0', 'UserData', struct('Type', 'numeric'), 'Tag', 'SPRockDensityEditField'); -handles.DPTab = uitab('Parent', handles.TabGroup3, 'Title', 'DP', 'Tag', 'DPTab'); +handles.DPTab = uipanel('Parent', handles.TabGroup3, 'Title', 'DP', 'Units', 'pixels', ... + 'Position', [0 0 1156 430], 'Tag', 'DPTab', 'Visible', 'off'); handles.kxTextAreaLabel = uicontrol('Parent', handles.DPTab, 'Style', 'text', 'Units', 'pixels', 'Position', [66 365 25 22], ... 'String', 'kx', 'HorizontalAlignment', 'right', 'Tag', 'kxTextAreaLabel'); @@ -261,11 +275,17 @@ handles.CommonCporLabel = uicontrol('Parent', handles.DiscretizationTab, 'Style' handles.CommonCporEditField = uicontrol('Parent', handles.DiscretizationTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [420 502 150 22], ... 'HorizontalAlignment', 'left', 'String', '0', 'UserData', struct('Type', 'numeric'), 'Tag', 'CommonCporEditField'); -handles.FlowTab = uitab('Parent', handles.TabGroup, 'Title', 'Flow', 'Tag', 'FlowTab'); +handles.FlowTab = uipanel('Parent', handles.TabGroup, 'Title', 'Flow', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'FlowTab', 'Visible', 'off'); -handles.TabGroup2 = uitabgroup('Parent', handles.FlowTab, 'Units', 'pixels', 'Position', [54 12 1120 267], 'Tag', 'TabGroup2'); +handles.FlowPageDropDown = uicontrol('Parent', handles.FlowTab, 'Style', 'popupmenu', 'Units', 'pixels', ... + 'Position', [54 286 160 22], 'String', {'GasWater', 'OilWater', 'MultiComponent'}, 'Value', 1, 'Tag', 'FlowPageDropDown'); -handles.GasWaterTab = uitab('Parent', handles.TabGroup2, 'Title', 'GasWater', 'Tag', 'GasWaterTab'); +handles.TabGroup2 = uipanel('Parent', handles.FlowTab, 'Units', 'pixels', 'Position', [54 12 1120 267], ... + 'BorderType', 'none', 'Tag', 'TabGroup2'); + +handles.GasWaterTab = uipanel('Parent', handles.TabGroup2, 'Title', 'GasWater', 'Units', 'pixels', ... + 'Position', [0 0 1120 267], 'Tag', 'GasWaterTab', 'Visible', 'on'); handles.ifpcglEditFieldLabel = uicontrol('Parent', handles.GasWaterTab, 'Style', 'text', 'Units', 'pixels', 'Position', [37 197 33 22], ... 'String', 'ifpcgl', 'HorizontalAlignment', 'right', 'Tag', 'ifpcglEditFieldLabel'); @@ -285,7 +305,8 @@ handles.PRFTextAreaLabel = uicontrol('Parent', handles.GasWaterTab, 'Style', 'te handles.GWPRFTextArea = uicontrol('Parent', handles.GasWaterTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [87 35 150 60], ... 'Max', 2, 'Min', 0, 'HorizontalAlignment', 'left', 'String', '', 'Tag', 'GWPRFTextArea'); -handles.OilWaterTab = uitab('Parent', handles.TabGroup2, 'Title', 'OilWater', 'Tag', 'OilWaterTab'); +handles.OilWaterTab = uipanel('Parent', handles.TabGroup2, 'Title', 'OilWater', 'Units', 'pixels', ... + 'Position', [0 0 1120 267], 'Tag', 'OilWaterTab', 'Visible', 'off'); handles.density_o_scEditFieldLabel = uicontrol('Parent', handles.OilWaterTab, 'Style', 'text', 'Units', 'pixels', 'Position', [242 199 75 22], ... 'String', 'density_o_sc', 'HorizontalAlignment', 'right', 'Tag', 'density_o_scEditFieldLabel'); @@ -348,7 +369,8 @@ handles.OWoil_modelDropDown = uicontrol('Parent', handles.OilWaterTab, 'Style', 'String', {''}, 'Value', 1, 'Tag', 'OWoil_modelDropDown'); setPopupDefaultValue(handles.OWoil_modelDropDown, ''); -handles.MultiComponentTab = uitab('Parent', handles.TabGroup2, 'Title', 'MultiComponent', 'Tag', 'MultiComponentTab'); +handles.MultiComponentTab = uipanel('Parent', handles.TabGroup2, 'Title', 'MultiComponent', 'Units', 'pixels', ... + 'Position', [0 0 1120 267], 'Tag', 'MultiComponentTab', 'Visible', 'off'); handles.cs_NcTextAreaLabel = uicontrol('Parent', handles.MultiComponentTab, 'Style', 'text', 'Units', 'pixels', 'Position', [16 191 38 22], ... 'String', 'cs_Nc', 'HorizontalAlignment', 'right', 'Tag', 'cs_NcTextAreaLabel'); @@ -557,19 +579,23 @@ handles.GasBetaNonDarcyLabel = uicontrol('Parent', handles.FlowTab, 'Style', 'te handles.FlowCommonGasBetaNonDarcyEditField = uicontrol('Parent', handles.FlowTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [743 426 100 22], ... 'HorizontalAlignment', 'left', 'String', '0', 'UserData', struct('Type', 'numeric'), 'Tag', 'FlowCommonGasBetaNonDarcyEditField'); -handles.WellsTab = uitab('Parent', handles.TabGroup, 'Title', 'Wells', 'Tag', 'WellsTab'); +handles.WellsTab = uipanel('Parent', handles.TabGroup, 'Title', 'Wells', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'WellsTab', 'Visible', 'off'); handles.Well1Table = uitable('Parent', handles.WellsTab, 'Units', 'pixels', 'Position', [43 194 446 167], ... - 'ColumnName', {'Well1'}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'Well1Table'); + 'ColumnName', {'well_name', 'nperf', 'index_xyz', 'rw', 'skin', 'well_type'}, ... + 'ColumnWidth', {90, 55, 95, 55, 55, 90}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'Well1Table'); handles.FractureWellLocationTable = uitable('Parent', handles.WellsTab, 'Units', 'pixels', 'Position', [737 520 445 100], ... - 'ColumnName', {'FractureWellLocation'}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'FractureWellLocationTable'); + 'ColumnName', {'x', 'y', 'z'}, 'ColumnWidth', {140, 140, 140}, ... + 'RowName', {}, 'ColumnEditable', true, 'Tag', 'FractureWellLocationTable'); handles.Well2Table = uitable('Parent', handles.WellsTab, 'Units', 'pixels', 'Position', [35 476 594 185], ... - 'ColumnName', {'Well2'}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'Well2Table'); + 'ColumnName', {'well_name', 'nperf', 'perfnum', 'rw', 'skin', 'well_type'}, ... + 'ColumnWidth', {100, 70, 120, 70, 70, 130}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'Well2Table'); handles.ScheduleTable = uitable('Parent', handles.WellsTab, 'Units', 'pixels', 'Position', [552 176 362 185], ... - 'ColumnName', {'Schedule'}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'ScheduleTable'); + 'ColumnName', {'Schedule'}, 'ColumnWidth', {100}, 'RowName', {}, 'ColumnEditable', true, 'Tag', 'ScheduleTable'); handles.TimeTextAreaLabel = uicontrol('Parent', handles.WellsTab, 'Style', 'text', 'Units', 'pixels', 'Position', [949 288 31 22], ... 'String', 'Time', 'HorizontalAlignment', 'right', 'Tag', 'TimeTextAreaLabel'); @@ -632,7 +658,8 @@ handles.SelectedFracWellDropDown = uicontrol('Parent', handles.WellsTab, 'Style' 'String', {''}, 'Value', 1, 'Tag', 'SelectedFracWellDropDown'); setPopupDefaultValue(handles.SelectedFracWellDropDown, ''); -handles.SolverRunTab = uitab('Parent', handles.TabGroup, 'Title', 'Solver&Run', 'Tag', 'SolverRunTab'); +handles.SolverRunTab = uipanel('Parent', handles.TabGroup, 'Title', 'Solver&Run', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'SolverRunTab', 'Visible', 'off'); handles.RunLogTextAreaLabel = uicontrol('Parent', handles.SolverRunTab, 'Style', 'text', 'Units', 'pixels', 'Position', [263 571 47 22], ... 'String', 'RunLog', 'HorizontalAlignment', 'right', 'Tag', 'RunLogTextAreaLabel'); @@ -679,7 +706,8 @@ handles.EpsMaxEditFieldLabel = uicontrol('Parent', handles.SolverRunTab, 'Style' handles.EpsMaxEditField = uicontrol('Parent', handles.SolverRunTab, 'Style', 'edit', 'Units', 'pixels', 'Position', [113 308 100 22], ... 'HorizontalAlignment', 'left', 'String', '0', 'UserData', struct('Type', 'numeric'), 'Tag', 'EpsMaxEditField'); -handles.ResultsTab = uitab('Parent', handles.TabGroup, 'Title', 'Results', 'Tag', 'ResultsTab'); +handles.ResultsTab = uipanel('Parent', handles.TabGroup, 'Title', 'Results', 'Units', 'pixels', ... + 'Position', [0 0 1247 698], 'Tag', 'ResultsTab', 'Visible', 'off'); handles.ResultAxes = axes('Parent', handles.ResultsTab, 'Units', 'pixels', 'Position', [217 22 987 585], 'Tag', 'ResultAxes'); @@ -726,7 +754,7 @@ handles.PlotWellDropDown = uicontrol('Parent', handles.ResultsTab, 'Style', 'pop 'String', {''}, 'Value', 1, 'Tag', 'PlotWellDropDown'); setPopupDefaultValue(handles.PlotWellDropDown, ''); -handles.PlotTimeStepSlider = uicontrol('Parent', handles.ResultsTab, 'Style', 'slider', 'Units', 'pixels', 'Position', [15 578 150 3], ... +handles.PlotTimeStepSlider = uicontrol('Parent', handles.ResultsTab, 'Style', 'slider', 'Units', 'pixels', 'Position', [15 574 150 20], ... 'Min', 0, 'Max', 100, 'Value', 0, 'Tag', 'PlotTimeStepSlider'); handles.PlotTimeStepValueLabel = uicontrol('Parent', handles.ResultsTab, 'Style', 'text', 'Units', 'pixels', 'Position', [54 609 106 22], ... diff --git a/gui_support/app/edit_edfm_guide_page.m b/gui_support/app/edit_edfm_guide_page.m new file mode 100644 index 0000000..f55ee22 --- /dev/null +++ b/gui_support/app/edit_edfm_guide_page.m @@ -0,0 +1,55 @@ +function edit_edfm_guide_page(pageName, figPath) +%EDIT_EDFM_GUIDE_PAGE Open EDFMSimulatorGuide.fig in GUIDE on one page. +% EDIT_EDFM_GUIDE_PAGE('Model') saves the main FIG with only the Model +% panel visible, then opens that same FIG in GUIDE. +% +% Save and close an already-open GUIDE editor before switching pages this +% way, otherwise GUIDE may keep an older in-memory copy. + +if nargin < 2 || strlength(string(figPath)) == 0 + figPath = fullfile(fileparts(mfilename('fullpath')), 'EDFMSimulatorGuide.fig'); +end + +if exist(figPath, 'file') ~= 2 + error('edit_edfm_guide_page:MissingFig', 'FIG file not found: %s', figPath); +end + +fig = openfig(figPath, 'invisible'); +cleanupObj = onCleanup(@() closeFigureIfValid(fig)); + +show_edfm_guide_page(fig, pageName); +syncSelectorValue(fig, pageName); +set(fig, 'Visible', 'on'); +savefig(fig, figPath); +close(fig); +delete(cleanupObj); + +guide(figPath); +end + +function syncSelectorValue(fig, pageName) +pageName = char(string(pageName)); +setPopupValue(findobj(fig, 'Tag', 'PageDropDown'), pageName); +setPopupValue(findobj(fig, 'Tag', 'DiscretizationPageDropDown'), pageName); +setPopupValue(findobj(fig, 'Tag', 'FlowPageDropDown'), pageName); +end + +function setPopupValue(handleObj, value) +if isempty(handleObj) || ~isgraphics(handleObj) + return; +end +items = get(handleObj, 'String'); +if ischar(items) + items = cellstr(items); +end +idx = find(strcmp(items, value), 1); +if ~isempty(idx) + set(handleObj, 'Value', idx); +end +end + +function closeFigureIfValid(fig) +if ~isempty(fig) && isgraphics(fig) + close(fig); +end +end diff --git a/gui_support/app/show_edfm_guide_page.m b/gui_support/app/show_edfm_guide_page.m new file mode 100644 index 0000000..ad33d7d --- /dev/null +++ b/gui_support/app/show_edfm_guide_page.m @@ -0,0 +1,91 @@ +function show_edfm_guide_page(figOrPage, pageName) +%SHOW_EDFM_GUIDE_PAGE Show one GUIDE page panel and hide the others. +% SHOW_EDFM_GUIDE_PAGE('Flow') finds the open EDFM GUIDE figure. +% SHOW_EDFM_GUIDE_PAGE(FIG, 'Flow') uses the specified figure. +% +% This helper is intended for GUIDE editing. The GUIDE Object Browser can +% turn a hidden panel on, but another visible panel may still cover it. + +if nargin == 1 + pageName = figOrPage; + fig = findOpenEdfmGuideFigure(); +else + fig = figOrPage; +end + +if isempty(fig) || ~isgraphics(fig) + error('show_edfm_guide_page:InvalidFigure', ... + ['No open EDFM GUIDE figure was found. Open EDFMSimulatorGuide.fig ', ... + 'in GUIDE first, or call show_edfm_guide_page(fig, pageName).']); +end + +pageTags = struct( ... + 'model', 'ModelTab', ... + 'grid', 'GridTab', ... + 'fracture', 'FractureTab', ... + 'discretization', 'DiscretizationTab', ... + 'flow', 'FlowTab', ... + 'wells', 'WellsTab', ... + 'solverrun', 'SolverRunTab', ... + 'solver_run', 'SolverRunTab', ... + 'results', 'ResultsTab', ... + 'sp', 'SPTab', ... + 'dp', 'DPTab', ... + 'gaswater', 'GasWaterTab', ... + 'oilwater', 'OilWaterTab', ... + 'multicomponent', 'MultiComponentTab'); + +key = lower(regexprep(char(string(pageName)), '[^a-zA-Z0-9_]', '')); +if ~isfield(pageTags, key) + error('show_edfm_guide_page:UnknownPage', 'Unknown page name: %s', char(string(pageName))); +end + +targetTag = pageTags.(key); +groups = { + {'ModelTab', 'GridTab', 'FractureTab', 'DiscretizationTab', 'FlowTab', 'WellsTab', 'SolverRunTab', 'ResultsTab'} + {'SPTab', 'DPTab'} + {'GasWaterTab', 'OilWaterTab', 'MultiComponentTab'} + }; + +for groupIndex = 1:numel(groups) + group = groups{groupIndex}; + if any(strcmp(group, targetTag)) + for i = 1:numel(group) + panel = findobj(fig, 'Tag', group{i}); + if ~isempty(panel) + if strcmp(group{i}, targetTag) + set(panel, 'Visible', 'on'); + try + uistack(panel, 'top'); + catch + end + else + set(panel, 'Visible', 'off'); + end + end + end + end +end +end + +function fig = findOpenEdfmGuideFigure() +fig = []; +figures = findall(0, 'Type', 'figure'); +for i = 1:numel(figures) + if hasEdfmPagePanels(figures(i)) + fig = figures(i); + return; + end +end +end + +function tf = hasEdfmPagePanels(fig) +requiredTags = {'ModelTab', 'ResultsTab', 'PageDropDown'}; +tf = true; +for i = 1:numel(requiredTags) + if isempty(findobj(fig, 'Tag', requiredTags{i})) + tf = false; + return; + end +end +end