mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Do alphabet sorting.
This commit is contained in:
parent
5f082ae4df
commit
66edb5066a
6 changed files with 198 additions and 50 deletions
|
@ -1,6 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MakeCWizard.title=C/Make Project
|
MakeCWizard.title=C/Make Project
|
||||||
MakeCWizard.description=Create a New C Project using 'make' to build it
|
MakeCWizard.description=Create a New C Project using 'make' to build it
|
||||||
MakeCWizard.task_name=Creating C project with Make builder...
|
MakeCWizard.task_name=Creating C project with Make builder...
|
||||||
|
@ -86,3 +84,11 @@ TogglePresentation.label=Change Presentation
|
||||||
TogglePresentation.tooltip=Enable/Disable Segmented Source Viewer
|
TogglePresentation.tooltip=Enable/Disable Segmented Source Viewer
|
||||||
TogglePresentation.description=Enable/Disable Segmented Source Viewer
|
TogglePresentation.description=Enable/Disable Segmented Source Viewer
|
||||||
|
|
||||||
|
# ------- LexicalSortingAction------------
|
||||||
|
|
||||||
|
LexicalSortingAction.label=Sort
|
||||||
|
LexicalSortingAction.description=Sorts the elements in the outliner
|
||||||
|
LexicalSortingAction.tooltip=Sort
|
||||||
|
LexicalSortingAction.tooltip.on=Do Not Sort
|
||||||
|
LexicalSortingAction.tooltip.off=Sort
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class MakeUIImages {
|
||||||
public static final ImageDescriptor DESC_OBJ_ERROR = createManaged(OBJ, IMG_OBJS_ERROR);
|
public static final ImageDescriptor DESC_OBJ_ERROR = createManaged(OBJ, IMG_OBJS_ERROR);
|
||||||
|
|
||||||
|
|
||||||
|
// For the outliner label provider.
|
||||||
public static final String IMG_TOOLS_MAKE_TARGET_BUILD = NAME_PREFIX + "target_build.gif"; //$NON-NLS-1$
|
public static final String IMG_TOOLS_MAKE_TARGET_BUILD = NAME_PREFIX + "target_build.gif"; //$NON-NLS-1$
|
||||||
public static final String IMG_TOOLS_MAKE_TARGET_ADD = NAME_PREFIX + "target_add.gif"; //$NON-NLS-1$
|
public static final String IMG_TOOLS_MAKE_TARGET_ADD = NAME_PREFIX + "target_add.gif"; //$NON-NLS-1$
|
||||||
public static final String IMG_TOOLS_MAKE_TARGET_DELETE = NAME_PREFIX + "target_delete.gif"; //$NON-NLS-1$
|
public static final String IMG_TOOLS_MAKE_TARGET_DELETE = NAME_PREFIX + "target_delete.gif"; //$NON-NLS-1$
|
||||||
|
@ -70,6 +71,8 @@ public class MakeUIImages {
|
||||||
public static final String IMG_OBJS_MAKEFILE_INCLUDE = NAME_PREFIX + "include_obj.gif"; //$NON-NLS-1$
|
public static final String IMG_OBJS_MAKEFILE_INCLUDE = NAME_PREFIX + "include_obj.gif"; //$NON-NLS-1$
|
||||||
public static final ImageDescriptor DESC_MAKEFILE_INCLUDE = createManaged(OBJ, IMG_OBJS_MAKEFILE_INCLUDE);
|
public static final ImageDescriptor DESC_MAKEFILE_INCLUDE = createManaged(OBJ, IMG_OBJS_MAKEFILE_INCLUDE);
|
||||||
|
|
||||||
|
public static final String IMG_TOOLS_ALPHA_SORTING= NAME_PREFIX + "alphab_sort_co.gif";
|
||||||
|
|
||||||
public static final String IMG_TOOLS_MAKEFILE_SEGMENT_EDIT= NAME_PREFIX + "segment_edit.gif";
|
public static final String IMG_TOOLS_MAKEFILE_SEGMENT_EDIT= NAME_PREFIX + "segment_edit.gif";
|
||||||
|
|
||||||
private static ImageDescriptor createManaged(String prefix, String name) {
|
private static ImageDescriptor createManaged(String prefix, String name) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.eclipse.jface.dialogs.ProgressMonitorDialog;
|
||||||
import org.eclipse.swt.widgets.Display;
|
import org.eclipse.swt.widgets.Display;
|
||||||
import org.eclipse.swt.widgets.Shell;
|
import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.ui.IStartup;
|
import org.eclipse.ui.IStartup;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
import org.eclipse.ui.IWorkbenchWindow;
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||||
|
|
||||||
|
@ -72,10 +73,24 @@ public class MakeUIPlugin extends AbstractUIPlugin implements IStartup {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the active workbench window or <code>null</code> if none
|
||||||
|
*/
|
||||||
public static IWorkbenchWindow getActiveWorkbenchWindow() {
|
public static IWorkbenchWindow getActiveWorkbenchWindow() {
|
||||||
return getDefault().getWorkbench().getActiveWorkbenchWindow();
|
return getDefault().getWorkbench().getActiveWorkbenchWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the active workbench page or <code>null</code> if none.
|
||||||
|
*/
|
||||||
|
public static IWorkbenchPage getActivePage() {
|
||||||
|
IWorkbenchWindow window= getActiveWorkbenchWindow();
|
||||||
|
if (window != null) {
|
||||||
|
return window.getActivePage();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the string from the plugin's resource bundle,
|
* Returns the string from the plugin's resource bundle,
|
||||||
* or 'key' if not found.
|
* or 'key' if not found.
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/**********************************************************************
|
||||||
|
* Copyright (c) 2002,2003 Rational Software Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - initial implementation
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.make.internal.ui.editor;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.make.core.makefile.IDirective;
|
||||||
|
import org.eclipse.cdt.make.core.makefile.IInferenceRule;
|
||||||
|
import org.eclipse.cdt.make.core.makefile.IMacroDefinition;
|
||||||
|
import org.eclipse.cdt.make.core.makefile.ISpecialRule;
|
||||||
|
import org.eclipse.cdt.make.internal.ui.MakeUIImages;
|
||||||
|
import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
|
||||||
|
import org.eclipse.jface.action.Action;
|
||||||
|
import org.eclipse.jface.viewers.TreeViewer;
|
||||||
|
import org.eclipse.jface.viewers.ViewerSorter;
|
||||||
|
|
||||||
|
public class LexicalSortingAction extends Action {
|
||||||
|
|
||||||
|
private static final String ACTION_NAME = "LexicalSortingAction";
|
||||||
|
private static final String DIALOG_STORE_KEY = ACTION_NAME + ".sort";
|
||||||
|
|
||||||
|
private LexicalMakefileSorter fSorter;
|
||||||
|
private TreeViewer fTreeViewer;
|
||||||
|
|
||||||
|
public LexicalSortingAction(TreeViewer treeViewer) {
|
||||||
|
super(MakeUIPlugin.getResourceString(ACTION_NAME + ".label"));
|
||||||
|
|
||||||
|
setDescription(MakeUIPlugin.getResourceString(ACTION_NAME + ".description"));
|
||||||
|
setToolTipText(MakeUIPlugin.getResourceString(ACTION_NAME + ".tooltip"));
|
||||||
|
MakeUIImages.setImageDescriptors(this, "tool16", MakeUIImages.IMG_TOOLS_ALPHA_SORTING);
|
||||||
|
|
||||||
|
fTreeViewer = treeViewer;
|
||||||
|
fSorter = new LexicalMakefileSorter();
|
||||||
|
boolean checked = MakeUIPlugin.getDefault().getDialogSettings().getBoolean(DIALOG_STORE_KEY);
|
||||||
|
valueChanged(checked, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
valueChanged(isChecked(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void valueChanged(boolean on, boolean store) {
|
||||||
|
setChecked(on);
|
||||||
|
fTreeViewer.setSorter(on ? fSorter : null);
|
||||||
|
|
||||||
|
String key = ACTION_NAME + ".tooltip" + (on ? ".on" : ".off");
|
||||||
|
setToolTipText(MakeUIPlugin.getResourceString(key));
|
||||||
|
if (store) {
|
||||||
|
MakeUIPlugin.getDefault().getDialogSettings().put(DIALOG_STORE_KEY, on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LexicalMakefileSorter extends ViewerSorter {
|
||||||
|
|
||||||
|
public boolean isSorterProperty(Object element, Object property) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int category(Object obj) {
|
||||||
|
if (obj instanceof IDirective) {
|
||||||
|
IDirective directive = (IDirective) obj;
|
||||||
|
if (directive instanceof IMacroDefinition) {
|
||||||
|
return 0;
|
||||||
|
} else if (directive instanceof ISpecialRule) {
|
||||||
|
return 1;
|
||||||
|
} else if (directive instanceof IInferenceRule) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -30,19 +30,16 @@ import org.eclipse.cdt.make.internal.core.makefile.NullMakefile;
|
||||||
import org.eclipse.cdt.make.internal.ui.MakeUIImages;
|
import org.eclipse.cdt.make.internal.ui.MakeUIImages;
|
||||||
import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
|
import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
|
||||||
import org.eclipse.cdt.make.ui.IWorkingCopyManager;
|
import org.eclipse.cdt.make.ui.IWorkingCopyManager;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.jface.action.IToolBarManager;
|
||||||
import org.eclipse.jface.text.IDocument;
|
|
||||||
import org.eclipse.jface.viewers.ILabelProvider;
|
import org.eclipse.jface.viewers.ILabelProvider;
|
||||||
import org.eclipse.jface.viewers.ISelection;
|
|
||||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
|
||||||
import org.eclipse.jface.viewers.ITreeContentProvider;
|
import org.eclipse.jface.viewers.ITreeContentProvider;
|
||||||
import org.eclipse.jface.viewers.LabelProvider;
|
import org.eclipse.jface.viewers.LabelProvider;
|
||||||
import org.eclipse.jface.viewers.SelectionChangedEvent;
|
|
||||||
import org.eclipse.jface.viewers.TreeViewer;
|
import org.eclipse.jface.viewers.TreeViewer;
|
||||||
import org.eclipse.jface.viewers.Viewer;
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.ui.IActionBars;
|
||||||
import org.eclipse.ui.IEditorInput;
|
import org.eclipse.ui.IEditorInput;
|
||||||
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
|
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
|
||||||
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
|
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
|
||||||
|
@ -222,19 +219,8 @@ public class MakefileContentOutlinePage extends ContentOutlinePage implements IC
|
||||||
public void createControl(Composite parent) {
|
public void createControl(Composite parent) {
|
||||||
super.createControl(parent);
|
super.createControl(parent);
|
||||||
TreeViewer viewer = getTreeViewer();
|
TreeViewer viewer = getTreeViewer();
|
||||||
|
|
||||||
/*
|
|
||||||
* We might want to implement our own content provider.
|
|
||||||
* This content provider should be able to work on a dom like tree
|
|
||||||
* structure that resembles the file contents.
|
|
||||||
*/
|
|
||||||
viewer.setContentProvider(new MakefileContentProvider());
|
viewer.setContentProvider(new MakefileContentProvider());
|
||||||
|
|
||||||
/*
|
|
||||||
* We probably also need our own label provider.
|
|
||||||
*/
|
|
||||||
viewer.setLabelProvider(new MakefileLabelProvider());
|
viewer.setLabelProvider(new MakefileLabelProvider());
|
||||||
|
|
||||||
if (fInput != null) {
|
if (fInput != null) {
|
||||||
viewer.setInput(fInput);
|
viewer.setInput(fInput);
|
||||||
}
|
}
|
||||||
|
@ -248,37 +234,6 @@ public class MakefileContentOutlinePage extends ContentOutlinePage implements IC
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* Method declared on ContentOutlinePage
|
|
||||||
*/
|
|
||||||
public void selectionChanged(SelectionChangedEvent event) {
|
|
||||||
|
|
||||||
super.selectionChanged(event);
|
|
||||||
|
|
||||||
ISelection selection = event.getSelection();
|
|
||||||
if (selection.isEmpty()) {
|
|
||||||
fEditor.resetHighlightRange();
|
|
||||||
} else if (selection instanceof IStructuredSelection){
|
|
||||||
Object element = ((IStructuredSelection) selection).getFirstElement();
|
|
||||||
if (element instanceof IDirective) {
|
|
||||||
IDirective statement = (IDirective)element;
|
|
||||||
int startLine = statement.getStartLine() - 1;
|
|
||||||
int endLine = statement.getEndLine() - 1;
|
|
||||||
try {
|
|
||||||
IDocument doc = fEditor.getDocumentProvider().getDocument(fInput);
|
|
||||||
int start = doc.getLineOffset(startLine);
|
|
||||||
int len = doc.getLineLength(endLine) - 1;
|
|
||||||
int length = (doc.getLineOffset(endLine) + len) - start;
|
|
||||||
fEditor.setHighlightRange(start, length, true);
|
|
||||||
} catch (IllegalArgumentException x) {
|
|
||||||
fEditor.resetHighlightRange();
|
|
||||||
} catch (BadLocationException e) {
|
|
||||||
fEditor.resetHighlightRange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the outline page.
|
* Updates the outline page.
|
||||||
*/
|
*/
|
||||||
|
@ -296,4 +251,15 @@ public class MakefileContentOutlinePage extends ContentOutlinePage implements IC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.ui.part.IPage#setActionBars(org.eclipse.ui.IActionBars)
|
||||||
|
*/
|
||||||
|
public void setActionBars(IActionBars actionBars) {
|
||||||
|
super.setActionBars(actionBars);
|
||||||
|
IToolBarManager toolBarManager= actionBars.getToolBarManager();
|
||||||
|
|
||||||
|
LexicalSortingAction action= new LexicalSortingAction(getTreeViewer());
|
||||||
|
toolBarManager.add(action);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,20 +12,30 @@ package org.eclipse.cdt.make.internal.ui.editor;
|
||||||
|
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.make.core.makefile.IDirective;
|
||||||
import org.eclipse.cdt.make.core.makefile.IMakefile;
|
import org.eclipse.cdt.make.core.makefile.IMakefile;
|
||||||
import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
|
import org.eclipse.cdt.make.internal.ui.MakeUIPlugin;
|
||||||
import org.eclipse.cdt.make.internal.ui.text.MakefileColorManager;
|
import org.eclipse.cdt.make.internal.ui.text.MakefileColorManager;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.jface.action.IAction;
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.ITextOperationTarget;
|
import org.eclipse.jface.text.ITextOperationTarget;
|
||||||
import org.eclipse.jface.text.source.ISourceViewer;
|
import org.eclipse.jface.text.source.ISourceViewer;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.jface.viewers.ISelectionChangedListener;
|
||||||
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.SelectionChangedEvent;
|
||||||
|
import org.eclipse.ui.IPartService;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
import org.eclipse.ui.editors.text.TextEditor;
|
import org.eclipse.ui.editors.text.TextEditor;
|
||||||
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
|
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
|
||||||
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
|
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
|
||||||
import org.eclipse.ui.texteditor.TextOperationAction;
|
import org.eclipse.ui.texteditor.TextOperationAction;
|
||||||
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
|
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
|
||||||
|
|
||||||
public class MakefileEditor extends TextEditor {
|
public class MakefileEditor extends TextEditor implements ISelectionChangedListener{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The page that shows the outline.
|
* The page that shows the outline.
|
||||||
|
@ -36,6 +46,7 @@ public class MakefileEditor extends TextEditor {
|
||||||
private MakefileContentOutlinePage getOutlinePage() {
|
private MakefileContentOutlinePage getOutlinePage() {
|
||||||
if (page == null) {
|
if (page == null) {
|
||||||
page = new MakefileContentOutlinePage(this);
|
page = new MakefileContentOutlinePage(this);
|
||||||
|
page.addSelectionChangedListener(this);
|
||||||
page.setInput(getEditorInput());
|
page.setInput(getEditorInput());
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
|
@ -109,4 +120,70 @@ public class MakefileEditor extends TextEditor {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
|
||||||
|
*/
|
||||||
|
public void selectionChanged(SelectionChangedEvent event) {
|
||||||
|
ISelection selection = event.getSelection();
|
||||||
|
if (selection.isEmpty()) {
|
||||||
|
resetHighlightRange();
|
||||||
|
} else if (selection instanceof IStructuredSelection){
|
||||||
|
if (!isActivePart() && MakeUIPlugin.getActivePage() != null) {
|
||||||
|
MakeUIPlugin.getActivePage().bringToTop(this);
|
||||||
|
}
|
||||||
|
Object element = ((IStructuredSelection) selection).getFirstElement();
|
||||||
|
if (element instanceof IDirective) {
|
||||||
|
IDirective statement = (IDirective)element;
|
||||||
|
setSelection(statement, !isActivePart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the editor is active.
|
||||||
|
*/
|
||||||
|
private boolean isActivePart() {
|
||||||
|
IWorkbenchWindow window= getSite().getWorkbenchWindow();
|
||||||
|
IPartService service= window.getPartService();
|
||||||
|
IWorkbenchPart part= service.getActivePart();
|
||||||
|
return part != null && part.equals(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSelection(IDirective directive, boolean moveCursor) {
|
||||||
|
int startLine = directive.getStartLine() - 1;
|
||||||
|
int endLine = directive.getEndLine() - 1;
|
||||||
|
try {
|
||||||
|
IDocument doc = getDocumentProvider().getDocument(getEditorInput());
|
||||||
|
int start = doc.getLineOffset(startLine);
|
||||||
|
int len = doc.getLineLength(endLine) - 1;
|
||||||
|
int length = (doc.getLineOffset(endLine) + len) - start;
|
||||||
|
setHighlightRange(start, length, true);
|
||||||
|
if (moveCursor) {
|
||||||
|
// Let see if we can move the cursor at the position also
|
||||||
|
String var = directive.toString().trim();
|
||||||
|
for (len = 0; len < var.length(); len++) {
|
||||||
|
char c = var.charAt(len);
|
||||||
|
if (! (Character.isLetterOrDigit(c) || c == '.' || c == '_')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
var = var.substring(0, len);
|
||||||
|
}
|
||||||
|
len = doc.search(start, var, true, true, true);
|
||||||
|
length = var.length();
|
||||||
|
if (len > -1 && length > 0) {
|
||||||
|
getSourceViewer().revealRange(len, length);
|
||||||
|
// Selected region begins one index after offset
|
||||||
|
getSourceViewer().setSelectedRange(len, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException x) {
|
||||||
|
resetHighlightRange();
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
resetHighlightRange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue