/*
 * Created on 2004-12-10
 *
 * Part of the Symbian development plug-in for Eclipse
 * Copyright (C) Mikołaj Zalewski, 2004
 */
package pl.zalewski.mikolaj.symbdev.ui.mmpedit;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;

import pl.zalewski.mikolaj.symbdev.SymbdevPlugin;
import pl.zalewski.mikolaj.symbdev.core.mmpmodel.IMMPModel;

/**
 * The linkers options section on the Options page of the MMP editor
 * 
 * @author mikolaj
 */
public class LinkerOptionsSection extends MMPSectionPart {

    public LinkerOptionsSection(Composite parent, FormToolkit toolkit, IMMPModel model) {
        super(parent, toolkit, "Linker", "Select options for the target executable", 2);
        fModel=model;
        fToolkit=toolkit;
        fNondefStack=toolkit.createButton(fContainer, "Non-default stack size", SWT.CHECK);
        TableWrapData td=new TableWrapData();
        td.colspan=2;
        fNondefStack.setLayoutData(td);
        fStack=addTextWithLabel("  Stack size", "");
        fNondefHeap=toolkit.createButton(fContainer, "Non-default heap size", SWT.CHECK);
        td=new TableWrapData();
        td.colspan=2;
        fNondefHeap.setLayoutData(td);
        
        Composite c=toolkit.createComposite(fContainer);
        td=new TableWrapData();
        td.colspan=2;
        c.setLayoutData(td);
        GridLayout gl=new GridLayout(4, false);
        c.setLayout(gl);
        
        toolkit.createLabel(c, "  Min: ");
        fMinHeap=toolkit.createText(c, "", SWT.BORDER);
        GridData gd=new GridData();
        gd.widthHint=60;
        fMinHeap.setLayoutData(gd);
                
        toolkit.createLabel(c, "  Max: ");
        fMaxHeap=toolkit.createText(c, "", SWT.BORDER);
        gd=new GridData();
        gd.widthHint=60;
        fMaxHeap.setLayoutData(gd);
        
        fPriority=addComboWithLabel("Priority", IMMPModel.fPriorities,
                0);
        
        fStackSizeListener=new Listener() {
            public void handleEvent(Event e) {
                stackSizeChanged();
            }			
        };
        fModel.addChangeListener(IMMPModel.CHANGE_STACKSIZE, fStackSizeListener);
        fHeapSizeListener=new Listener() {
            public void handleEvent(Event e) {
                heapSizeChanged();
            }			
        };
        fModel.addChangeListener(IMMPModel.CHANGE_HEAPSIZE, fHeapSizeListener);
        
        fNondefStack.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                nondefStackClicked();
            }			
        });
        fNondefHeap.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                nondefHeapClicked();
            }			
        });
        fStack.addListener(SWT.FocusOut, new Listener() {
            public void handleEvent(Event e) {
                updateStack();
            }			
        });
        fStack.addListener(SWT.Dispose, new Listener() {
            public void handleEvent(Event e) {
                updateStack();
            }			
        });
        fMinHeap.addListener(SWT.FocusOut, new Listener() {
            public void handleEvent(Event e) {
                updateHeapMin();
            }
        });
        fMinHeap.addListener(SWT.Dispose, new Listener() {
            public void handleEvent(Event e) {
                updateHeapMin();
            }
        });
        fMaxHeap.addListener(SWT.FocusOut, new Listener() {
            public void handleEvent(Event e) {
                updateHeapMax();
            }
        });
        fMaxHeap.addListener(SWT.Dispose, new Listener() {
            public void handleEvent(Event e) {
                updateHeapMax();
            }
        });
        
        fPriorityListener=new Listener() {
            public void handleEvent(Event e) {
                priorityChanged();
            }			
        };
        fModel.addChangeListener(IMMPModel.CHANGE_PRIORITY, fPriorityListener);
        fPriority.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event e) {
                updatePriority();
            }			
        });

        // init
        heapSizeChanged();    
        stackSizeChanged();
        priorityChanged();
        contentCreated();
    }
    
    public void heapSizeChanged()
    {
        if (fMinHeap.isDisposed() || fMaxHeap.isDisposed()
                || fNondefHeap.isDisposed())
            return;
        int heapmin=fModel.getHeapMin(),
            heapmax=fModel.getHeapMax();
        boolean nondef=(heapmin!=0 && heapmax!=0);
        fNondefHeap.setSelection(nondef);
        fMinHeap.setEditable(nondef);
        fMaxHeap.setEditable(nondef);
        if (!nondef)
        {
            fMinHeap.setText("");
            fMaxHeap.setText("");            
        } else
        {
            fMinHeap.setText(""+heapmin);
            fMaxHeap.setText(""+heapmax);
        }
    }
    
    public void stackSizeChanged()
    {
        if (fNondefStack.isDisposed() || fStack.isDisposed())
            return;
        int stack=fModel.getStackSize();
        fNondefStack.setSelection(stack!=0);
        fStack.setEditable(stack!=0);
        if (stack==0)
            fStack.setText("");
        	else fStack.setText(""+stack);
    }
    
    public void priorityChanged()
    {
        int i;
        String prio=fModel.getPriority();
        String[] items;
        for (i=0; i<IMMPModel.fPriorities.length; i++)
            if (IMMPModel.fPriorities[i].equalsIgnoreCase(prio))
                break;
        if (i<IMMPModel.fPriorities.length)
            items=new String[IMMPModel.fPriorities.length];
            else items=new String[IMMPModel.fPriorities.length+1];
        System.arraycopy(IMMPModel.fPriorities, 0, items, 0,
                IMMPModel.fPriorities.length);
        items[i]=prio;
        fPriority.setItems(items);
        fPriority.select(i);
    }
    
    public void updateStack()
    {
        try
        {
            int stack=stringToInt(fStack.getText());
            fModel.setStackSize(stack);
        }
        catch (CoreException e)
        {
            SymbdevPlugin.showError(e, "Couldn't store the stack size", getSection().getShell());
        }
    }
    
    public void updateHeapMin()
    {
        try
        {
            int val=stringToInt(fMinHeap.getText());
            fModel.setHeapMin(val);
        }
        catch (CoreException e)
        {
            SymbdevPlugin.showError(e, "Couldn't store the minimal heap size", getSection().getShell());
        }        
    }

    public void updateHeapMax()
    {
        try
        {
            int val=stringToInt(fMaxHeap.getText());
            fModel.setHeapMax(val);
        }
        catch (CoreException e)
        {
            SymbdevPlugin.showError(e, "Couldn't store the maximal heap size", getSection().getShell());
        }        
    }
    
    public void updatePriority()
    {
        int sel=fPriority.getSelectionIndex();
        if (sel==-1)
            return;
        String newPrio=fPriority.getItem(sel);
        String prio=fModel.getPriority();
        if (newPrio.equals(prio))
            return;
        try {
            fModel.setPriority(newPrio);
        } catch (CoreException e) {
            SymbdevPlugin.showError(e, "Couldn't store the priority heap size", getSection().getShell());
        }
    }
    
    public void nondefStackClicked()
    {
        boolean sel=fNondefStack.getSelection();
        try {
            fModel.setStackSize(sel?8192:0);
        } catch (CoreException e) {
            SymbdevPlugin.showError(e, null, getSection().getShell());            
        }
    }
    
    public void nondefHeapClicked()
    {
        boolean sel=fNondefHeap.getSelection();
        try {
            fModel.setHeapMin(sel?4096:0);
            fModel.setHeapMax(sel?1048576:0);
        } catch (CoreException e) {
            SymbdevPlugin.showError(e, null, getSection().getShell());            
        }        
    }
    
    public void dispose() {
        fModel.removeChangeListener(IMMPModel.CHANGE_HEAPSIZE, fHeapSizeListener);
        fModel.removeChangeListener(IMMPModel.CHANGE_STACKSIZE, fStackSizeListener);
        fModel.removeChangeListener(IMMPModel.CHANGE_PRIORITY, fPriorityListener);
        super.dispose();
    }
    
    Button fNondefStack;
    Button fNondefHeap;
    Combo fPriority;
    Text fStack;
    Text fMinHeap, fMaxHeap;
    FormToolkit fToolkit;
    IMMPModel fModel;
    Listener fHeapSizeListener;
    Listener fStackSizeListener;
    Listener fPriorityListener;
}