classdef Controller2 < handle
    %UNTITLED Summary of this class goes here
    %   Detailed explanation goes here
    
    properties
        m
        v
        synchListener
    end
    
    methods
        function obj = Controller2(model)
            %UNTITLED Construct an instance of this class
            %   Detailed explanation goes here
            obj.m = model;
            obj.startGUI();
        end
        
        function startGUI(obj)
            obj.v = View(obj.m);
            set(obj.v.fig, 'SizeChangedFcn',{@obj.onFigResize},...
                'CloseRequestFcn',{@obj.onFigExit},...
                'WindowButtonMotionFcn',{@obj.onMouseMovement},...
                'WindowButtonUpFcn', {@obj.onButtonUp},...
                'KeyPressFcn', {@obj.keyPress},...
                'KeyReleaseFcn',{@obj.keyPress});
            set(obj.v.ax,'ButtonDownFcn',{@obj.onButtonDown})
            obj.v.fig.Visible = 'on';
            
            % Calibration panel
            set(obj.v.tab1.Children(1),'Callback',{@obj.tab1Btn_1})
            set(obj.v.tab1.Children(2),'Callback',{@obj.tab1Btn_2})
            set(obj.v.tab1.Children(3),'Callback',{@obj.tab1Btn_3})
            set(obj.v.tab1.Children(4),'Callback',{@obj.tab1Btn_4})
            set(obj.v.tab1.Children(5),'Callback',{@obj.tab1Btn_5})
            set(obj.v.tab1.Children(6),'Callback',{@obj.tab1Btn_6})
            set(obj.v.tab1.Children(7),'Callback',{@obj.tab1Btn_7})
            set(obj.v.tab1.Children(8),'Callback',{@obj.tab1Btn_8})
            
            for i = [2:3,5:8]
                set(obj.v.tab1.Children(i),'enable','off')
            end
            
            % Control points panel
            set(obj.v.btnTab4{1},'Callback',{@obj.saveCrtlPoints})
            set(obj.v.btnTab4{2},'Callback',{@obj.saveCrtlPoints})
            set(obj.v.btnTab4{3},'Callback',{@obj.saveCrtlPoints})
            set(obj.v.btnTab4{4},'Callback',{@obj.saveCrtlPoints})
            set(obj.v.popupStrings(1),'Callback',{@obj.selectCtrlPoints})
            set(obj.v.btnTab4{5},'Callback',{@obj.animateMLS})
            
            % menu callbacks
            obj.v.menuBar.ImportCtrlPoints.MenuSelectedFcn = {@obj.MenuSelected};
            obj.v.menuBar.ExportCtrlPoints.MenuSelectedFcn = {@obj.MenuSelected};
            obj.v.menuBar.ExportImg.MenuSelectedFcn = {@obj.MenuSelected};
            obj.v.importImgTypesPrint;
            obj.v.menuBar.ImportImg.MenuSelectedFcn = {@obj.MenuSelected};
            
            % iamge panel
            addlistener(obj.m,'ImgStructChanged',@(o,e) obj.updateTab5);
%             set(obj.v.btnTab5{1},'Callback',{@obj.updateTab5})
            set(obj.v.popupStringsImg(1),'Callback',{@obj.selectImg})
            %             set(obj.v.popupStringsImg(2),'Callback',{@obj.updateTab5})
            set(obj.v.btnTab5{3},'Callback',{@obj.SendCorrectedImageController});
            set(obj.v.btnTab5{4},'Callback',{@obj.ImageMenuSelected})
            set(obj.v.btnTab5{5},'Callback',{@obj.ImageMenuSelected})
            set(obj.v.btnTab5{6},'Callback',{@obj.ImageMenuSelected})
            set(obj.v.btnTab5{7},'Callback',{@obj.ImageMenuSelected})
            set(obj.v.btnTab5{8},'Callback',{@obj.ImageMenuSelected})
            obj.updateTab5();
            
            %projector menu callbacks
            obj.v.menuBar.ProjectorConnect.MenuSelectedFcn = {@obj.MenuProjectorConnect};
            obj.v.menuBar.ProjectorON.MenuSelectedFcn = {@obj.MenuProjectorON};
            obj.v.menuBar.ProjectorOFF.MenuSelectedFcn = {@obj.MenuProjectorOFF};
            obj.v.menuBar.ProjectorSend.MenuSelectedFcn = {@obj.SendCorrectedImageController};
            obj.v.menuBar.ProjectorSynch.MenuSelectedFcn = {@obj.synchImgCtrl};
            obj.v.menuBar.ProjectorPreDeform.MenuSelectedFcn = {@obj.applyPreDeform};
            obj.v.menuBar.ProjectorBrightnessCorr.MenuSelectedFcn = {@obj.applyBrightnessCorr};
            obj.v.menuBar.ProjectorBrightnessCorr2.MenuSelectedFcn = {@obj.applyBrightnessCorr2};
            
            %BBB listener
            addlistener(obj.m.TCP, 'PinPROJ_ON_EXT','PostSet', @(o,e) obj.updateProjectorMenu());
            addlistener(obj.m.TCP, 'DISP_CTRLconf','PostSet', @(o,e) obj.updateProjectorMenu());
            addlistener(obj.m.TCP, 'isopen','PostSet', @(o,e) obj.updateProjectorMenu());
            addlistener(obj.m, 'applyCorrection','PostSet', @(o,e) obj.updateProjectorMenu());
            
            
            %Camera menu
            obj.v.menuBar.CamSelect.MenuSelectedFcn = {@obj.CamSelectPopup};
            obj.v.menuBar.Cam_Open.MenuSelectedFcn = {@obj.CamShowPreviewPopup};
            obj.v.menuBar.Cam_Close.MenuSelectedFcn = {@obj.CamClosePreviewPopup};
            obj.v.menuBar.Cam_Snap.MenuSelectedFcn = {@obj.CamSnapPopup};
            
            disp('Done')
            
            %listener for img
            %addlistener(m, 'displayedImg','PostSet', @(o,e) sendImg(m));
            
            
            %
            %
            %             % menu callbacks
            %             v.menuBar.ImportCtrlPoints.MenuSelectedFcn = {@MenuSelected,m,v};
            %             v.menuBar.ExportCtrlPoints.MenuSelectedFcn = {@MenuSelected,m,v};
            %             v.importImgTypesPrint;
            %             v.menuBar.ImportImg.MenuSelectedFcn = {@MenuSelected,m,v};
            %             addlistener(m,'ImgStructChanged',@(o,e) updateTab5(m,v));
            %             set(v.btnTab5{1},'Callback',@(o,e) updateTab5(m,v))
            %             set(v.popupStringsImg(1),'Callback',{@selectImg,m,v})
            %             set(v.popupStringsImg(2),'Callback',@(o,e) updateTab5(m,v))
            %
            %             updateTab5(m,v);
            %
            %             % projector menu callbacks
            %             v.menuBar.ProjectorConnect.MenuSelectedFcn = {@MenuProjectorConnect,m,v};
            %             v.menuBar.ProjectorON.MenuSelectedFcn = {@MenuProjectorON,m,v};
            %             v.menuBar.ProjectorOFF.MenuSelectedFcn = {@MenuProjectorOFF,m,v};
            %
            %             % BBB listener
            %             addlistener(m.TCP, 'PinPROJ_ON_EXT','PostSet', @(o,e) updateProjectorMenu(m.TCP,v));
            %             addlistener(m.TCP, 'DISP_CTRLconf','PostSet', @(o,e) updateProjectorMenu(m.TCP,v));
            %             addlistener(m.TCP, 'isopen','PostSet', @(o,e) updateProjectorMenu(m.TCP,v));
        end
        
        
        %% window
        function onFigResize(obj,hObject,eventdata)
            obj.v.ReSizingWindowFcn(obj.m.libraryImgs(obj.m.assigned2Imgs.ToDisplay).imgSize);
        end
        
        
        
        
        function onFigExit(obj,hObject,eventdata)
            selection = questdlg('Do yo want to close both figure and model?',...
                'Close Request Function',...
                'Yes Both','Only Figure','No','Yes Both');
            switch selection
                case 'Yes Both'
                    delete(obj.m)
                    delete(obj.v.fig)
                    delete(obj.v)
                    disp('Done closing')
                case 'Only Figure'
                    delete(obj.v.fig)
                    delete(obj.v)
                    disp('Done closing')
                case 'No'
                    disp('Exit cancelled')
            end
        end
        %% mouse
        function onButtonDown(obj,hObject,eventdata)
            % img callback = hit test done by Matlab
            if obj.v.mouse.buttonDown == 0%handles.mouse_btn == 0
                obj.v.mouse.buttonDown = 1; %handles.mouse_btn = 1;
                obj.v.mouse.buttonPulse = 1; % handles.get_point = 1
            end
            obj.mouseLogic()
        end
        function onButtonUp(obj,hObject,eventdata)
            obj.v.mouse.buttonDown = 0;
            obj.v.mouse.holdAndDrag = 0;
            % mouseLogic(v,m)
            obj.m.moveCtrlPoint(obj.v.mouse.position,'clear');
        end
        function onMouseMovement(obj,hObject,eventdata)
            % get position inside figure axis
            obj.v.mouse.position = round(obj.v.ax.CurrentPoint(1,1:2));
            
            X = obj.v.img.XData;
            Y = obj.v.img.YData;
            
            % set to NaN if outside of figure axis
            if any(obj.v.mouse.position > [X(2),Y(2)] | obj.v.mouse.position < [X(1),Y(1)])
                obj.v.mouse.position = [NaN,NaN];
            end
            
            obj.m.closestCtrlPoint(obj.v.mouse.position);
            
            obj.mouseLogic()
        end
        
        function mouseLogic(obj)
            obj.v.mouse;
            if obj.v.mouse.buttonDown == 1 && all(~isnan( obj.v.mouse.position))
                % is a click or hold?
                if obj.v.mouse.buttonPulse == 1
                    clickPosition = obj.v.mouse.position;
                    % ctrl button pressed within image?
                    if obj.v.key.control == 1
                        % add new point
                        if isempty(obj.m.selectedCtrlPoints) || obj.m.ctrlPoints(obj.m.selectedCtrlPoints).allowEdit == 1
                            obj.m.addCtrlPoint(clickPosition(1),clickPosition(2))
                        else
                            fprintf('Control points locked for editing, go to MLS settings')
                        end
                        %fprintf('\nCtrl & (%d,%d)\n',clickPosition(1),clickPosition(2))
                    elseif obj.v.key.shift == 1
                        % remove closest point within range
                        obj.m.deleteClosestPoint()
                        %fprintf('\nShift & (%d,%d)\n',clickPosition(1),clickPosition(2))
                    else
                        %printHelp(clickPosition)
                        obj.m.moveCtrlPoint(obj.v.mouse.position,'hold');
                    end
                end
                obj.m.moveCtrlPoint(obj.v.mouse.position)
                
                obj.v.mouse.buttonPulse = 0;
            end
            
        end
        function printHelp(mousePos)
            if any(isnan(mousePos))
                fprintf('Click on image')
            else
                fprintf('Mouse position: (%d,%d)',mousePos(1),mousePos(2))
            end
            % prints how to control the GUI if no p or q points are added
            fprintf('\nAdd control points first!\n')
            fprintf('-------------------------\n')
            fprintf('Ctrl + Mouse Click to add control point\n')
            fprintf('Shift + Mouse Click to remove point\n')
            fprintf('Mouse click + Drag to add deform destination point\n')
        end
        %% keypress
        function keyPress(obj,hObject,eventdata)
            % compare button eventdata key with v.key structure names {'control';'shift'}
            if any(strcmp(fieldnames(obj.v.key),eventdata.Key))
                % if 'KeyPress' than 1, if 'KeyRelease' than 0
                new_stat = strcmp(eventdata.EventName,'KeyPress');
                if new_stat ~= obj.v.key.(eventdata.Key)
                    obj.v.key.(eventdata.Key) = new_stat;
                end
            end
        end
        
        %% buttons
        function ButtonsAssignCallbacks(obj,Tab)
            for i = 1:length(Tab.Children)
                %@(varargin)obj.onMouseMovement(varargin{:})
                callbackFcnName = strcat('@(varargin)obj.',Tab.Tag,'Btn_',Tab.Children(i).Tag,'(varargin{:})');
                set(Tab.Children(i),'Callback',{str2func(callbackFcnName)})
            end
            for i = [2:3,5:8]
                set(Tab.Children(i),'enable','off')
            end
        end
        
        %% hTab1 - calibration tab
        function tab1Btn_1(obj,hObject,~)
            %disp('Button 1 pressed')
            % aquire QR corner img
            img = obj.m.acqQRCalibCam2Plane(1);
            if ~isempty(img)
                obj.v.tab1.Children(5).Enable = 'on';
            end
        end
        function tab1Btn_5(obj,hObject,~)
            %disp('Button 5 pressed')
            prompt = {'Enter binarization sensitivity (usually 0-0.3):','Minimal QR corner line thickness (imopen & imclose):',...
                'Scan directions (1-3) for QR marker (horizontal,vertical,diagonal)', 'How many directions must contain marker pattern to be valid 1-3',...
                'QR pattern line tolerance (spec: 0.5)'};
            title = 'Input';
            dims = [1 50];
            definput = {'0','3','3','3','0.6'};
            answer = inputdlg(prompt,title,dims,definput);
            
            if ~isempty(answer)
                obj.v.tab1.Children(2).Enable = 'off';
                for i = 1:length(answer)
                    arg{i} = str2num(answer{i});
                end
                
                if length(arg)<5 || any([arg{:}]<0) || arg{3} > 3 || arg{3} < 1 || arg{1} > 1
                    error('Try again')
                end
                if arg{4} > arg{3}, arg{4} = arg{3};end
                arg{3} = strcat(num2str(arg{4}),'of',num2str(arg{3}));
                
                
                
                Tform = obj.m.runQRCalibCam2Plane(1, arg{1},arg{2}, arg{3}, arg{5});
                
                if ~isempty(Tform)
                    obj.v.tab1.Children(2).Enable = 'on';
                end
            end
        end
        
        
        function tab1Btn_2(obj,hObject,~)
            %disp('Button 2 pressed')
            prompt = {'Multiplication of delay for first image'};
            title = 'Input';
            dims = [1 30];
            definput = {'2'};
            answer = inputdlg(prompt,title,dims,definput);
            
            if ~isempty(answer)
                obj.v.tab1.Children(6).Enable = 'off';
                arg = str2num(answer{1});
                if length(arg)<1
                    error('Try again')
                end
                arg = round(arg);
                out = obj.m.acqDarkFieldClearField(arg);
                
                if ~isempty(out)
                    obj.v.tab1.Children(6).Enable = 'on';
                end
            end
            
        end
        
        function tab1Btn_6(obj,hObject,~)
            %disp('Button 6 pressed')
            obj.v.tab1.Children(3).Enable = 'off';
            out = obj.m.runDarkFieldClearField();
            if ~isempty(out)
                obj.v.tab1.Children(3).Enable = 'on';
            end
        end
        
        function tab1Btn_3(obj,hObject,~)
            %disp('Button 3 pressed')
            obj.v.tab1.Children(7).Enable = 'off';
            gridSize = [15 15]; delaySnap = 2;
            out = obj.m.sendCheckerboard(gridSize,delaySnap);
            if ~isempty(out)
                obj.v.tab1.Children(7).Enable = 'on';
            end
        end
        function tab1Btn_4(obj,hObject,~)
            %disp('Button 4 pressed')
            img = obj.m.improc.testCheckerboard(obj.m.improc.TestImgSize,[15 15],0);
            obj.m.sendCorrectedImage(img);
            obj.m.displayedImg = img;
        end
        
        
        function tab1Btn_7(obj,hObject,~)
            obj.v.tab1.Children(8).Enable = 'off';
            out = obj.m.detectCheckerboard();
            if ~isempty(out)
                obj.v.tab1.Children(8).Enable = 'on';
            end
        end
        function tab1Btn_8(obj,hObject,~)
            obj.v.tab1.Children(8).Enable = 'off';
            out = obj.m.findPreDefrom( obj.m.improc.gridM);
            if ~isempty(out)
                obj.v.tab1.Children(8).Enable = 'on';
                obj.updateProjectorMenu();
            end
        end
        
        %% hTab3
        function saveCrtlPoints(obj,hObject,~)
            name = '';
            if strcmp(hObject.String,'Load')
                f.Text = 'Import control points';
                obj.MenuSelected(f);
            elseif ~strcmp(hObject.String,'Save')
                name = string(inputdlg('Please enter a name:',hObject.String,[1,50]));
            end
            obj.m.saveDispExpressions(hObject.String,name);
        end
        function selectCtrlPoints(obj,hObject,~)
            obj.m.selectDispCtrlPoint(hObject.Value)
        end
        function animateMLS(obj,~,~)
            obj.m.saveDispExpressions('Save','');
            parameters = {obj.v.popupStrings(1).Value,0,obj.v.popupStrings(1).Value,1,0,1,20,10,0};
            obj.m.animateMLS(parameters)
        end
        
        %%
        function updateTab5(obj,~,~)
            
            selectedID = obj.m.assigned2Imgs.ToDisplay;
            
            % if filter on
            %             if obj.v.btnTab5{1}.Value
            %                 % get string to search for in library
            %                 filterString = obj.v.popupStringsImg(2).String(obj.v.popupStringsImg(2).Value);
            %                 % find the indexes containig string
            %                 filteredID = find(cell2mat(cellfun(@(x)  any(strcmp(x,filterString)),{obj.m.libraryImgs(:).usedIn},'UniformOutput',false)));
            %             else
            % else all indexes
            filteredID = 1:length(obj.m.libraryImgs);
            %             end
            
            % update strings
            filteredNames = {obj.m.libraryImgs(filteredID).Name};
            
            
            % if displayed image not in filtered
            if ~any(ismember(selectedID,filteredID))
                filteredID = [selectedID,filteredID];
                filteredNames = [{sprintf('%s*',obj.m.libraryImgs(selectedID).Name)},filteredNames(:)'];
            end
            % transform id
            selectedID = find(filteredID == selectedID);
            
            filterableKeys = unique(vertcat(obj.m.libraryImgs(:).usedIn));
            
            % save
            obj.v.btnTab5{2}.Key = filteredID;
            
            %             obj.v.popupStringsImg(2).String = filterableKeys;
            obj.v.popupStringsImg(1).String = filteredNames;
            obj.v.popupStringsImg(1).Value = selectedID;
        end
        
        function selectImg(obj,src,event)
            % pass key to dictrionary -> library index
            IDKeys = 1:length(obj.m.libraryImgs);
            if ~isempty(obj.v.btnTab5{2})
                IDKeys = obj.v.btnTab5{2}.Key;
            end
            
            obj.m.displayImg(IDKeys(src.Value));
        end
        
        function checkBoxFilter(obj,src,~)
            %obj.popupStringsImg(1).String
            obj.v.btnTab5{2}.customP = find(cell2mat(cellfun(@(x)  any(strcmp(x,'task2')),{obj.m.libraryImgs(:).usedIn},'UniformOutput',false)));
            %obj.v.btnTab5{2}.customP = find({obj.m.libraryImgs(:).usedIn},'task0');
            obj.v.updatePopupImg;
        end
        
        function ImageMenuSelected(obj,src,~)
            switch src.String
                case 'Save As'
                     s.Text = 'Export Image'; obj.MenuSelected(s);
                case 'Load'
                    s.Text = 'Import Image';obj.MenuSelected(s);
                case 'Rename'
                    newName = string(inputdlg('Please enter a name:','Rename img', [1,50],{obj.m.libraryImgs(obj.m.assigned2Imgs.ToDisplay).Name}));
                    obj.m.renameImageInLib(newName);
                case 'fliplr()'
                    obj.m.flipImgInLib('fliplr()');
                case 'flipud()'
                    obj.m.flipImgInLib('flipud()');
            end
        end
        
        %% MENU
        function MenuSelected(obj,src,event,~)
            %x = [('PQ','*.mat','Select One or More Files','MultiSelect','on')];
            path = erase(mfilename('fullpath'),extractAfter(mfilename('fullpath'),'matlab_code'));
            switch src.Text
                case 'Import control points'
                    path = fullfile(path,'Model','SavedCtrlPoints','*.mat');
                    [file,path] = uigetfile(path,'Select One or More Files to import Control Points from','MultiSelect','on');
                    if file ~= 0
                        obj.m.loadCtrlPoints(path,file)
                    end
                    disp(file);
                case 'Export control points'
                    if isempty(obj.m.selectedCtrlPoints)
                        helpdlg({'No control points selected','add control points'},'Error: Export control points');
                    else
                        id = obj.m.selectedCtrlPoints;
                        n = strcat([erase(obj.m.ctrlPoints(id).tag,'.mat')],'.mat');
                        path = fullfile(path,'Model','SavedCtrlPoints','\',n);
                        [file,path] = uiputfile(path,'Select PQ export file name and location');
                        if file ~= 0
                            obj.m.saveCtrlPoints(path,file)
                        end
                    end
                case 'Import Image'
                    path = fullfile(path,'Model','img');
                    % import dialog, filter allow only matlab supported img file formats
                    [file,path] = uigetfile(obj.v.menuBar.ImgImportIn,'Select Img To Import',path,'MultiSelect','on');
                    % uigetfile(path,'Select One or More Files to import Control Points from','MultiSelect','on');
                    if ~isequal(file,0)
                        obj.m.loadImg(path,file)
                    end
                    
                case 'Export Image'
                    id = obj.m.assigned2Imgs.ToDisplay;
                    if isempty(id)
                        helpdlg({'No image selected','import image'},'Error: Export image');
                    else
                        
                        n = strcat(obj.m.libraryImgs(id).Name,'.bmp');
                        path = fullfile(path,'Model','img',n);
                       
                        [file,path] = uiputfile(obj.v.menuBar.ImgExportOut,'Select image export file name and location',path);
                        if file ~= 0
                            obj.m.saveImgFromLib(path,file)
                        end
                    end
                    
                    
                case 'Load image folder'
                    path = fullfile(path,'Model','SavedCtrlPoints','*.mat');
                    path = uigetdir
                    
                otherwise
                    disp('Unknown')
            end
            
            
        end
        
        %% Projector menu
        function updateProjectorMenu(obj,~,~)
            obj.v.menuBar.ProjectorPreDeform.Enable = 'off';
            obj.v.menuBar.ProjectorBrightnessCorr.Enable = 'off';
            obj.v.menuBar.ProjectorBrightnessCorr2.Enable = 'off';
            if obj.m.TCP.isopen
                s = 'Status: Connected';
                if obj.m.TCP.PinPROJ_ON_EXT && obj.m.TCP.DISP_CTRLconf
                    s = strcat(s,' - Light On');
                else
                    s = strcat(s,' - Light Off');
                end
                obj.v.menuBar.ProjectorConnect.Text = 'Disconnect';
                obj.v.menuBar.ProjectorON.Enable = 'on';
                obj.v.menuBar.ProjectorOFF.Enable = 'on';
                obj.v.menuBar.ProjectorSend.Enable = 'on';
                obj.v.menuBar.ProjectorSynch.Enable = 'on';
                if ~isempty(obj.m.improc.calibOutData)
                    obj.v.menuBar.ProjectorPreDeform.Enable = 'on';
                    obj.v.menuBar.ProjectorBrightnessCorr.Enable = 'on';
                    obj.v.menuBar.ProjectorBrightnessCorr2.Enable = 'on';
                end
            else
                s = 'Status: Disconected - simulation mode';
                obj.v.menuBar.ProjectorConnect.Text = 'Connect';
                obj.v.menuBar.ProjectorON.Enable = 'off';
                obj.v.menuBar.ProjectorOFF.Enable = 'off';
                obj.v.menuBar.ProjectorSend.Enable = 'off';
                obj.v.menuBar.ProjectorSynch.Enable = 'off';
                
                 if ~isempty(obj.m.improc.calibOutData)
                    obj.v.menuBar.ProjectorPreDeform.Enable = 'on';
                    obj.v.menuBar.ProjectorBrightnessCorr.Enable = 'on';
                    obj.v.menuBar.ProjectorBrightnessCorr2.Enable = 'on';
                end
            end
            set(obj.v.menuBar.ProjectorStatus,'Text',s)
            
            % check boxes
            obj.v.menuBar.ProjectorSynch.Checked = 'on';
            if isempty(obj.synchListener), obj.v.menuBar.ProjectorSynch.Checked = 'off';end
            
            obj.v.menuBar.ProjectorPreDeform.Checked = 'off';
            obj.v.menuBar.ProjectorBrightnessCorr.Checked = 'off';
            obj.v.menuBar.ProjectorBrightnessCorr2.Checked = 'off';
            if obj.m.applyCorrection(1), obj.v.menuBar.ProjectorPreDeform.Checked = 'on';end
            if obj.m.applyCorrection(2), obj.v.menuBar.ProjectorBrightnessCorr.Checked = 'on';end
            if obj.m.applyCorrection(3), obj.v.menuBar.ProjectorBrightnessCorr2.Checked = 'on';end
            
        end
        function MenuProjectorConnect(obj,~,~)
            if obj.m.TCP.isopen
                obj.m.TCP.close;
            else
                obj.m.TCP.open;
            end
        end
        function MenuProjectorON(obj,~,~)
            if obj.m.TCP.isopen
                obj.m.TCP.TurnONProjector;
            end
        end
        
        function MenuProjectorOFF(obj,~,~)
            if obj.m.TCP.isopen
                obj.m.TCP.TurnOFFProjector;
            end
        end
        
        function SendCorrectedImageController(obj,~,~)
            obj.m.sendCorrectedImage();
        end
        
        function synchImgCtrl(obj,src,event)
            %obj.m.applyCorrection(1) = ~obj.m.applyCorrection(1);
            if isempty(obj.synchListener)
                obj.synchListener = addlistener(obj.m, 'displayedImg','PostSet', @(o,e) obj.SendCorrectedImageController);
            else
                delete(obj.synchListener);
                obj.synchListener = [];
            end
            obj.updateProjectorMenu();
        end
        

        function applyPreDeform(obj,~,~)
            obj.m.applyCorrection(1) = ~obj.m.applyCorrection(1);
            obj.SendCorrectedImageController();
        end
        
        function applyBrightnessCorr(obj,~,~)
            obj.m.applyCorrection(2) = ~obj.m.applyCorrection(2);
              if obj.m.applyCorrection(2)
                obj.m.applyCorrection(3) = false;
              end
            obj.SendCorrectedImageController();
        end
        
        function applyBrightnessCorr2(obj,~,~)
            obj.m.applyCorrection(3) = ~obj.m.applyCorrection(3);
            if obj.m.applyCorrection(3)
                obj.m.applyCorrection(2) = false;
            end
            obj.SendCorrectedImageController();
        end
        
        %% camera menu
        function CamSelectPopup(obj,~,~)
            cams = webcamlist;
            idx = listdlg('ListString',cams,'SelectionMode','single');
            if ~isempty(idx)
                obj.m.CamName = cams{idx};
            end
        end
        
        function CamShowPreviewPopup(obj,~,~)
            obj.m.CamOpen();
            if ~isempty(obj.m.Cam)
                obj.m.Cam.preview;
            end
            obj.v.menuBar.Cam_Close.Enable = 'on';
        end
        function CamClosePreviewPopup(obj,~,~)
            if ~isempty(obj.m.Cam)
                obj.m.Cam.closePreview;
                obj.m.CamClose();
                obj.v.menuBar.Cam_Close.Enable = 'off';
            end
        end
        function CamSnapPopup(obj,~,~)
            if ~isempty(obj.m.Cam)
                figure;imshow(obj.m.Cam.snapshot);
            else
                 obj.m.CamOpen();
                 figure;imshow(obj.m.Cam.snapshot);
                 obj.m.CamClose;
            end
                 
        end        
    end
end

