提交 58eec7a6 编写于 作者: S Serge Rider

#3632 Multiline cell value editor. UI model refactoring


Former-commit-id: 271d2c06
上级 f0ccb8a4
......@@ -291,7 +291,7 @@ public class DataSourceDescriptor
@Nullable
@Override
@Property(viewable = true, order = 2)
@Property(viewable = true, multiline = true, order = 2)
public String getDescription()
{
return description;
......
......@@ -439,7 +439,7 @@ public class DriverDescriptor extends AbstractDescriptor implements DBPDriver
}
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
......@@ -365,7 +365,7 @@ public class DB2DataType extends DB2Object<DBSObject> implements DBSDataType, DB
@Nullable
@Override
@Property(viewable = false, editable = false)
@Property(viewable = false, editable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -253,7 +253,7 @@ public class DB2Index extends JDBCTableIndex<DB2Schema, DB2TableBase> {
@Nullable
@Override
@Property(viewable = false, editable = false)
@Property(viewable = false, editable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -215,7 +215,7 @@ public class DB2Package extends DB2SchemaObject implements DBPRefreshableObject
@Nullable
@Override
@Property(viewable = false, order = 9)
@Property(viewable = false, multiline = true, order = 9)
public String getDescription()
{
return remarks;
......
......@@ -373,7 +373,7 @@ public class DB2Routine extends DB2Object<DBSObject>
@Nullable
@Override
@Property(viewable = false)
@Property(viewable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -497,7 +497,7 @@ public class DB2Schema extends DB2GlobalObject implements DBSSchema, DBPRefresha
@Nullable
@Override
@Property(viewable = false, editable = false)
@Property(viewable = false, editable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -306,7 +306,7 @@ public class DB2Sequence extends DB2SchemaObject implements DBSSequence, DBPRefr
@Nullable
@Override
@Property(viewable = false, editable = true, updatable = true)
@Property(viewable = false, editable = true, updatable = true, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -125,7 +125,7 @@ public class DB2StorageGroup extends DB2GlobalObject implements DBPNamedObject {
@Nullable
@Override
@Property(viewable = false)
@Property(viewable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -253,7 +253,7 @@ public abstract class DB2TableBase extends JDBCTable<DB2DataSource, DB2Schema>
@Nullable
@Override
@Property(viewable = false, order = 99, editable = true, updatable = true)
@Property(viewable = false, order = 99, editable = true, updatable = true, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -317,7 +317,7 @@ public class DB2TableColumn extends JDBCTableColumn<DB2TableBase>
@Nullable
@Override
@Property(viewable = true, order = 999, editable = true, updatable = true)
@Property(viewable = true, order = 999, editable = true, updatable = true, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -141,7 +141,7 @@ public class DB2TableUniqueKey extends JDBCTableConstraint<DB2Table> {
@Nullable
@Override
@Property(viewable = true, editable = false, order = 4)
@Property(viewable = true, editable = false, multiline = true, order = 4)
public String getDescription()
{
return remarks;
......
......@@ -261,7 +261,7 @@ public class DB2Tablespace extends DB2GlobalObject implements DBPNamedObject, DB
@Nullable
@Override
@Property(viewable = false)
@Property(viewable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -339,7 +339,7 @@ public class DB2Trigger extends DB2SchemaObject implements DBSTrigger, DB2Source
@Nullable
@Override
@Property(viewable = false)
@Property(viewable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -135,7 +135,7 @@ public abstract class DB2ViewBase extends DB2TableBase implements DB2SourceObjec
@Nullable
@Override
@Property(viewable = false, editable = false, updatable = false)
@Property(viewable = false, editable = false, updatable = false, multiline = true)
public String getDescription()
{
return super.getDescription();
......
......@@ -178,7 +178,7 @@ public class DB2XMLSchema extends DB2SchemaObject implements DBPRefreshableObjec
@Nullable
@Override
@Property(viewable = false, order = 20, updatable = true)
@Property(viewable = false, order = 20, updatable = true, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -114,7 +114,7 @@ public class DB2RemoteServer extends DB2GlobalObject implements DBPRefreshableOb
return version;
}
@Property(viewable = true, editable = false, order = 5)
@Property(viewable = true, editable = false, multiline = true, order = 5)
public String getRemarks()
{
return remarks;
......
......@@ -91,7 +91,7 @@ public class DB2RemoteServerOption extends DB2Object<DB2RemoteServer> {
return createTime;
}
@Property(viewable = true, editable = false, order = 5)
@Property(viewable = true, editable = false, multiline = true, order = 5)
public String getRemarks()
{
return remarks;
......
......@@ -115,7 +115,7 @@ public class DB2Wrapper extends DB2GlobalObject implements DBPRefreshableObject
return library;
}
@Property(viewable = true, order = 5)
@Property(viewable = true, multiline = true, order = 5)
public String getRemarks()
{
return remarks;
......
......@@ -209,7 +209,7 @@ public class DB2Module extends DB2SchemaObject implements DBSProcedureContainer,
@Nullable
@Override
@Property(viewable = false)
@Property(viewable = false, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -131,7 +131,7 @@ public class DB2Role extends DB2Grantee implements DBPSaveableObject, DBARole, D
@Nullable
@Override
@Property(viewable = true)
@Property(viewable = true, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -194,7 +194,7 @@ public class ExasolBaseObjectGrant implements DBAPrivilege {
}
@Override
@Property(hidden = true)
@Property(hidden = true, multiline = true)
public String getDescription()
{
// No Description available
......
......@@ -60,7 +60,7 @@ public class ExasolConnectionGrant
}
@Override
@Property(hidden = true)
@Property(hidden = true, multiline = true)
public String getDescription()
{
return null;
......
......@@ -67,7 +67,7 @@ public class ExasolRole extends ExasolGrantee implements DBARole, DBPNamedObjec
return name;
}
@Property(viewable = true, updatable=true, editable=true, order = 10)
@Property(viewable = true, updatable=true, editable=true, multiline = true, order = 10)
public String getDescription() {
return description;
}
......
......@@ -58,7 +58,7 @@ public class ExasolSystemGrant implements DBAPrivilege {
}
@Override
@Property(hidden=true)
@Property(hidden=true, multiline = true)
public String getDescription()
{
return "";
......
......@@ -81,7 +81,7 @@ public class ExasolUser extends ExasolGrantee
}
@Override
@Property(viewable = true, updatable=true, editable=true, order = 100)
@Property(viewable = true, updatable=true, editable=true, multiline = true, order = 100)
public String getDescription()
{
return this.description;
......
......@@ -124,7 +124,7 @@ public class ExasolConnection
}
@Override
@Property(viewable = true, editable= true, updatable=true, order = 50)
@Property(viewable = true, editable= true, updatable=true, multiline = true, order = 50)
public String getDescription()
{
return this.comment;
......
......@@ -255,7 +255,7 @@ public class ExasolDataType extends ExasolObject<DBSObject> implements DBSDataTy
@Nullable
@Override
@Property(viewable = false, editable = false)
@Property(viewable = false, editable = false, multiline = true)
public String getDescription() {
return null;
}
......
......@@ -113,7 +113,7 @@ public class ExasolFunction
@Nullable
@Override
@Property(viewable = true, editable = true, updatable = true, order = 11)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 11)
public String getDescription() {
return this.remarks;
}
......
......@@ -246,7 +246,7 @@ public class ExasolSchema extends ExasolGlobalObject implements DBSSchema, DBPNa
return createTime;
}
@Property(viewable = true, editable = true, updatable = true, order = 3)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 3)
public String getDescription() {
return remarks;
}
......
......@@ -112,7 +112,7 @@ public class ExasolScript extends AbstractProcedure<ExasolDataSource, ExasolSche
@Nullable
@Override
@Property(viewable = true, editable = true, updatable = true, order = 11)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 11)
public String getDescription() {
return this.remarks;
}
......
......@@ -63,7 +63,7 @@ public abstract class ExasolTableBase extends JDBCTable<ExasolDataSource, Exasol
@Nullable
@Override
@Property(viewable = false, order = 99, editable = true, updatable = true)
@Property(viewable = false, order = 99, editable = true, updatable = true, multiline = true)
public String getDescription()
{
return remarks;
......
......@@ -234,7 +234,7 @@ public class ExasolTableColumn extends JDBCTableColumn<ExasolTableBase>
@Nullable
@Override
@Property(viewable = true, order = 999, editable = true, updatable = true)
@Property(viewable = true, order = 999, editable = true, updatable = true, multiline = true)
public String getDescription() {
return remarks;
}
......
......@@ -117,7 +117,7 @@ public class ExasolTableUniqueKey extends JDBCTableConstraint<ExasolTable> imple
@Nullable
@Override
@Property(viewable = false, editable = false, order = 4)
@Property(viewable = false, editable = false, multiline = true, order = 4)
public String getDescription() {
return null;
}
......
......@@ -77,7 +77,7 @@ public class ExasolView extends ExasolTableBase implements ExasolSourceObject {
@Override
@Property(viewable = true, editable = false, updatable = false, order = 40)
@Property(viewable = true, editable = false, updatable = false, multiline = true, order = 40)
public String getDescription() {
return super.getDescription();
}
......
......@@ -45,7 +45,7 @@ public class GenericDataType extends JDBCDataType<GenericStructContainer>
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return super.getDescription();
......
......@@ -71,7 +71,7 @@ public class GenericSchema extends GenericObjectContainer implements DBSSchema
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return null;
......
......@@ -63,7 +63,7 @@ public class GenericSequence implements DBSSequence, DBPQualifiedObject
@Nullable
@Override
@Property(viewable = true, order = 10)
@Property(viewable = true, multiline = true, order = 10)
public String getDescription() {
return description;
}
......
......@@ -56,7 +56,7 @@ public abstract class GenericSynonym implements DBSAlias, DBSObject, DBPQualifie
@Nullable
@Override
@Property(viewable = true, order = 10)
@Property(viewable = true, multiline = true, order = 10)
public String getDescription() {
return description;
}
......
......@@ -210,7 +210,7 @@ public class GenericTable extends JDBCTable<GenericDataSource, GenericStructCont
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
......@@ -162,7 +162,7 @@ public class GenericTableColumn extends JDBCTableColumn<GenericTable> implements
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return remarks;
......
......@@ -80,7 +80,7 @@ public class GenericTableIndex extends JDBCTableIndex<GenericStructContainer, Ge
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return null;
......
......@@ -55,7 +55,7 @@ public class GenericTrigger implements DBSTrigger, GenericScriptObject
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
......@@ -51,7 +51,7 @@ public class SQLServerTable extends GenericTable implements DBPOverloadedObject
return super.getDescription();
}
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription(DBRProgressMonitor monitor) throws DBException {
String description = getDescription();
if (description != null || !isSqlServer()) {
......
......@@ -101,7 +101,7 @@ public class MySQLCharset extends MySQLInformation {
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
......@@ -110,7 +110,7 @@ public class MySQLEvent extends MySQLInformation implements MySQLSourceObject {
@Nullable
@Override
@Property(viewable = true, category = CAT_DETAILS, order = 100)
@Property(viewable = true, multiline = true, category = CAT_DETAILS, order = 100)
public String getDescription()
{
return eventComment;
......
......@@ -157,7 +157,7 @@ public class MySQLPartition extends JDBCTableObject<MySQLTable>
@Nullable
@Override
@Property(viewable = true, order = 5)
@Property(viewable = true, multiline = true, order = 5)
public String getDescription()
{
return description;
......@@ -223,7 +223,7 @@ public class MySQLPartition extends JDBCTableObject<MySQLTable>
return checksum;
}
@Property(viewable = true, order = 16)
@Property(viewable = true, multiline = true, order = 16)
public String getComment()
{
return comment;
......
......@@ -72,7 +72,7 @@ public class MySQLTable extends MySQLTableBase
@Property(viewable = true, editable = true, updatable = true, order = 4) public long getAutoIncrement() { return autoIncrement; }
@Property(viewable = false, editable = true, updatable = true, listProvider = CharsetListProvider.class, order = 5) public MySQLCharset getCharset() { return charset; }
@Property(viewable = false, editable = true, updatable = true, listProvider = CollationListProvider.class, order = 6) public MySQLCollation getCollation() { return collation; }
@Property(viewable = true, editable = true, updatable = true, order = 100) public String getDescription() { return description; }
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 100) public String getDescription() { return description; }
@Property(category = CATEGORY_STATISTICS, viewable = true, order = 10) public long getRowCount() { return rowCount; }
@Property(category = CATEGORY_STATISTICS, viewable = false, order = 11) public long getAvgRowLength() { return avgRowLength; }
......
......@@ -329,7 +329,7 @@ public class MySQLTableColumn extends JDBCTableColumn<MySQLTableBase> implements
this.collation = collation;
}
@Property(viewable = true, editable = true, updatable = true, order = 100)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 100)
public String getComment()
{
return comment;
......
......@@ -106,7 +106,7 @@ public class MySQLTableIndex extends JDBCTableIndex<MySQLCatalog, MySQLTable> im
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return indexComment;
......
......@@ -152,7 +152,7 @@ public abstract class OracleTrigger<PARENT extends DBSObject> extends OracleObje
@Nullable
@Override
@Property(order = 11)
@Property(multiline = true, order = 11)
public String getDescription()
{
return description;
......
......@@ -248,7 +248,7 @@ public abstract class PostgreAttribute<OWNER extends DBSEntity & PostgreObject>
@Nullable
@Override
@Property(viewable = true, editable = true, updatable = true, order = 100)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 100)
public String getDescription() {
return description;
}
......
......@@ -160,7 +160,7 @@ public class PostgreIndex extends JDBCTableIndex<PostgreSchema, PostgreTableBase
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
......@@ -461,7 +461,7 @@ public class PostgreProcedure extends AbstractProcedure<PostgreDataSource, Postg
@Nullable
@Override
@Property(viewable = true, editable = true, updatable = true, order = 200)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 200)
public String getDescription()
{
return super.getDescription();
......
......@@ -52,7 +52,7 @@ public class SQLiteDataType extends JDBCDataType<SQLiteDataSource> {
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return super.getDescription();
......
......@@ -104,7 +104,7 @@ public class VerticaProjectionColumn extends JDBCTableColumn<VerticaProjection>
return super.getDescription();
}
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription(DBRProgressMonitor monitor) throws DBException {
return description;
}
......
......@@ -62,7 +62,7 @@ public class VerticaTableColumn extends GenericTableColumn
@Nullable
@Override
@Property(viewable = true, editable = true, updatable = true, order = 100)
@Property(viewable = true, editable = true, updatable = true, multiline = true, order = 100)
public String getDescription()
{
return super.getDescription();
......
......@@ -68,6 +68,7 @@ Export-Package: org.jkiss.dbeaver,
org.jkiss.dbeaver.runtime,
org.jkiss.dbeaver.runtime.jobs,
org.jkiss.dbeaver.runtime.net,
org.jkiss.dbeaver.runtime.properties,
org.jkiss.dbeaver.runtime.ui,
org.jkiss.dbeaver.utils
Bundle-ClassPath: .
......
......@@ -72,7 +72,7 @@ public abstract class AbstractProcedure<
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
......@@ -86,7 +86,7 @@ public abstract class AbstractTrigger implements DBSTrigger, DBPQualifiedObject,
@Nullable
@Override
@Property(viewable = true, order = 100)
@Property(viewable = true, multiline = true, order = 100)
public String getDescription()
{
return description;
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
/**
* Lazy properties listener
*/
public interface ILazyPropertyLoadListener {
void handlePropertyLoad(Object object, DBPPropertyDescriptor property, Object propertyValue, boolean completed);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
/**
* Lazy properties listener
*/
public interface ILazyPropertyLoadListener {
void handlePropertyLoad(Object object, DBPPropertyDescriptor property, Object propertyValue, boolean completed);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
/**
* Interface for filters. Can accept or reject items.
*/
public interface IPropertyFilter {
/**
* Determines if the given property passes this filter.
*/
boolean select(DBPPropertyDescriptor toTest);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
/**
* Interface for filters. Can accept or reject items.
*/
public interface IPropertyFilter {
/**
* Determines if the given property passes this filter.
*/
boolean select(DBPPropertyDescriptor toTest);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.edit.DBECommandContext;
/**
* Editable property source
*/
public interface IPropertySourceEditable {
boolean isEditable(Object object);
DBECommandContext getCommandContext();
// void addPropertySourceListener(IPropertySourceListener listener);
// void removePropertySourceListener(IPropertySourceListener listener);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.edit.DBECommandContext;
/**
* Editable property source
*/
public interface IPropertySourceEditable {
boolean isEditable(Object object);
DBECommandContext getCommandContext();
// void addPropertySourceListener(IPropertySourceListener listener);
// void removePropertySourceListener(IPropertySourceListener listener);
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
/**
* Property source which allows editing of multiple objects.
*/
public interface IPropertySourceMulti extends DBPPropertySource {
boolean isPropertySet(Object object, ObjectPropertyDescriptor id);
Object getPropertyValue(@Nullable DBRProgressMonitor monitor, Object object, ObjectPropertyDescriptor prop);
boolean isPropertyResettable(Object object, ObjectPropertyDescriptor prop);
void resetPropertyValue(@Nullable DBRProgressMonitor monitor, Object object, ObjectPropertyDescriptor prop);
void setPropertyValue(@Nullable DBRProgressMonitor monitor, Object object, ObjectPropertyDescriptor prop, Object value)
throws IllegalArgumentException;
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
/**
* Property source which allows editing of multiple objects.
*/
public interface IPropertySourceMulti extends DBPPropertySource {
boolean isPropertySet(Object object, ObjectPropertyDescriptor id);
Object getPropertyValue(@Nullable DBRProgressMonitor monitor, Object object, ObjectPropertyDescriptor prop);
boolean isPropertyResettable(Object object, ObjectPropertyDescriptor prop);
void resetPropertyValue(@Nullable DBRProgressMonitor monitor, Object object, ObjectPropertyDescriptor prop);
void setPropertyValue(@Nullable DBRProgressMonitor monitor, Object object, ObjectPropertyDescriptor prop, Object value)
throws IllegalArgumentException;
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.meta.IPropertyCacheValidator;
import org.jkiss.dbeaver.model.meta.LazyProperty;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.meta.PropertyGroup;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.utils.BeanUtils;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.Method;
import java.util.*;
/**
* Abstract object attribute
*/
public abstract class ObjectAttributeDescriptor {
static final Log log = Log.getLog(ObjectAttributeDescriptor.class);
public static final Comparator<ObjectAttributeDescriptor> ATTRIBUTE_DESCRIPTOR_COMPARATOR = new Comparator<ObjectAttributeDescriptor>() {
@Override
public int compare(ObjectAttributeDescriptor o1, ObjectAttributeDescriptor o2) {
return o1.getOrderNumber() - o2.getOrderNumber();
}
};
private final DBPPropertySource source;
private ObjectPropertyGroupDescriptor parent;
private int orderNumber;
private String id;
private Method getter;
private boolean isLazy;
private IPropertyCacheValidator cacheValidator;
private Class<?> declaringClass;
public ObjectAttributeDescriptor(
DBPPropertySource source,
ObjectPropertyGroupDescriptor parent,
Method getter,
String id,
int orderNumber)
{
this.source = source;
this.parent = parent;
this.getter = getter;
this.orderNumber = orderNumber;
this.id = id;
if (CommonUtils.isEmpty(this.id)) {
this.id = BeanUtils.getPropertyNameFromGetter(getter.getName());
}
declaringClass = parent == null ? getter.getDeclaringClass() : parent.getDeclaringClass();
if (this.getter.getParameterTypes().length > 0 && getter.getParameterTypes()[0] == DBRProgressMonitor.class) {
this.isLazy = true;
}
if (isLazy) {
final LazyProperty lazyInfo = getter.getAnnotation(LazyProperty.class);
if (lazyInfo != null) {
try {
cacheValidator = lazyInfo.cacheValidator().newInstance();
} catch (Exception e) {
log.warn("Can't instantiate lazy cache validator '" + lazyInfo.cacheValidator().getName() + "'", e);
}
}
}
}
public Class<?> getDeclaringClass()
{
return declaringClass;
}
public DBPPropertySource getSource()
{
return source;
}
public int getOrderNumber()
{
return orderNumber;
}
@NotNull
public String getId()
{
return id;
}
public Method getGetter()
{
return getter;
}
public boolean isNameProperty() {
return id.equals(DBConstants.PROP_ID_NAME);
}
public boolean isRemote()
{
return isLazy || parent != null && parent.isRemote();
}
public boolean isLazy()
{
return isLazy;
}
public boolean isLazy(Object object, boolean checkParent)
{
if (isLazy && cacheValidator != null) {
if (parent != null) {
if (parent.isLazy(object, true)) {
return true;
}
try {
// Parent isn't lazy so use null progress monitor
object = parent.getGroupObject(object, null);
} catch (Exception e) {
log.debug(e);
return true;
}
}
return !cacheValidator.isPropertyCached(object, id);
}
return isLazy || (checkParent && parent != null && parent.isLazy(object, checkParent));
}
public IPropertyCacheValidator getCacheValidator()
{
return cacheValidator;
}
public ObjectPropertyGroupDescriptor getParent()
{
return parent;
}
public abstract String getCategory();
public abstract String getDescription();
public static List<ObjectPropertyDescriptor> extractAnnotations(
DBPPropertySource source,
Class<?> theClass,
IPropertyFilter filter)
{
List<ObjectPropertyDescriptor> annoProps = new ArrayList<ObjectPropertyDescriptor>();
extractAnnotations(source, null, theClass, annoProps, filter);
return annoProps;
}
public static List<ObjectPropertyDescriptor> extractAnnotations(
DBPPropertySource source,
Collection<Class<?>> classList,
IPropertyFilter filter)
{
List<ObjectPropertyDescriptor> annoProps = new ArrayList<>();
for (Class<?> objectClass : classList) {
annoProps.addAll(ObjectAttributeDescriptor.extractAnnotations(source, objectClass, filter));
}
Collections.sort(annoProps, ATTRIBUTE_DESCRIPTOR_COMPARATOR);
return annoProps;
}
static void extractAnnotations(DBPPropertySource source, ObjectPropertyGroupDescriptor parent, Class<?> theClass, List<ObjectPropertyDescriptor> annoProps, IPropertyFilter filter)
{
Method[] methods = theClass.getMethods();
Map<String, Method> passedNames = new HashMap<>();
for (Method method : methods) {
String methodFullName = method.getDeclaringClass().getName() + "." + method.getName();
final Method prevMethod = passedNames.get(methodFullName);
if (prevMethod != null) {
// The same method but probably with another return type
final Class<?> prevReturnType = prevMethod.getReturnType();
final Class<?> newReturnType = method.getReturnType();
if (newReturnType == null || prevReturnType == null || newReturnType == prevReturnType || !prevReturnType.isAssignableFrom(newReturnType)) {
continue;
}
// Let it another chance. New return types seems to be subclass of previous
}
final PropertyGroup propGroupInfo = method.getAnnotation(PropertyGroup.class);
if (propGroupInfo != null && method.getReturnType() != null) {
// Property group
ObjectPropertyGroupDescriptor groupDescriptor = new ObjectPropertyGroupDescriptor(source, parent, method, propGroupInfo, filter);
annoProps.addAll(groupDescriptor.getChildren());
} else {
final Property propInfo = method.getAnnotation(Property.class);
if (propInfo == null || !BeanUtils.isGetterName(method.getName()) || method.getReturnType() == null) {
continue;
}
// Single property
ObjectPropertyDescriptor desc = new ObjectPropertyDescriptor(source, parent, propInfo, method);
if (filter != null && !filter.select(desc)) {
continue;
}
if (prevMethod != null) {
// Remove previous anno
for (Iterator<ObjectPropertyDescriptor> iter = annoProps.iterator(); iter.hasNext(); ) {
if (iter.next().getId().equals(desc.getId())) {
iter.remove();
}
}
}
annoProps.add(desc);
passedNames.put(methodFullName, method);
}
}
Collections.sort(annoProps, ATTRIBUTE_DESCRIPTOR_COMPARATOR);
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.meta.IPropertyCacheValidator;
import org.jkiss.dbeaver.model.meta.LazyProperty;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.meta.PropertyGroup;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.utils.BeanUtils;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.Method;
import java.util.*;
/**
* Abstract object attribute
*/
public abstract class ObjectAttributeDescriptor {
static final Log log = Log.getLog(ObjectAttributeDescriptor.class);
public static final Comparator<ObjectAttributeDescriptor> ATTRIBUTE_DESCRIPTOR_COMPARATOR = new Comparator<ObjectAttributeDescriptor>() {
@Override
public int compare(ObjectAttributeDescriptor o1, ObjectAttributeDescriptor o2) {
return o1.getOrderNumber() - o2.getOrderNumber();
}
};
private final DBPPropertySource source;
private ObjectPropertyGroupDescriptor parent;
private int orderNumber;
private String id;
private Method getter;
private boolean isLazy;
private IPropertyCacheValidator cacheValidator;
private Class<?> declaringClass;
public ObjectAttributeDescriptor(
DBPPropertySource source,
ObjectPropertyGroupDescriptor parent,
Method getter,
String id,
int orderNumber)
{
this.source = source;
this.parent = parent;
this.getter = getter;
this.orderNumber = orderNumber;
this.id = id;
if (CommonUtils.isEmpty(this.id)) {
this.id = BeanUtils.getPropertyNameFromGetter(getter.getName());
}
declaringClass = parent == null ? getter.getDeclaringClass() : parent.getDeclaringClass();
if (this.getter.getParameterTypes().length > 0 && getter.getParameterTypes()[0] == DBRProgressMonitor.class) {
this.isLazy = true;
}
if (isLazy) {
final LazyProperty lazyInfo = getter.getAnnotation(LazyProperty.class);
if (lazyInfo != null) {
try {
cacheValidator = lazyInfo.cacheValidator().newInstance();
} catch (Exception e) {
log.warn("Can't instantiate lazy cache validator '" + lazyInfo.cacheValidator().getName() + "'", e);
}
}
}
}
public Class<?> getDeclaringClass()
{
return declaringClass;
}
public DBPPropertySource getSource()
{
return source;
}
public int getOrderNumber()
{
return orderNumber;
}
@NotNull
public String getId()
{
return id;
}
public Method getGetter()
{
return getter;
}
public boolean isNameProperty() {
return id.equals(DBConstants.PROP_ID_NAME);
}
public boolean isRemote()
{
return isLazy || parent != null && parent.isRemote();
}
public boolean isLazy()
{
return isLazy;
}
public boolean isLazy(Object object, boolean checkParent)
{
if (isLazy && cacheValidator != null) {
if (parent != null) {
if (parent.isLazy(object, true)) {
return true;
}
try {
// Parent isn't lazy so use null progress monitor
object = parent.getGroupObject(object, null);
} catch (Exception e) {
log.debug(e);
return true;
}
}
return !cacheValidator.isPropertyCached(object, id);
}
return isLazy || (checkParent && parent != null && parent.isLazy(object, checkParent));
}
public IPropertyCacheValidator getCacheValidator()
{
return cacheValidator;
}
public ObjectPropertyGroupDescriptor getParent()
{
return parent;
}
public abstract String getCategory();
public abstract String getDescription();
public static List<ObjectPropertyDescriptor> extractAnnotations(
DBPPropertySource source,
Class<?> theClass,
IPropertyFilter filter)
{
List<ObjectPropertyDescriptor> annoProps = new ArrayList<ObjectPropertyDescriptor>();
extractAnnotations(source, null, theClass, annoProps, filter);
return annoProps;
}
public static List<ObjectPropertyDescriptor> extractAnnotations(
DBPPropertySource source,
Collection<Class<?>> classList,
IPropertyFilter filter)
{
List<ObjectPropertyDescriptor> annoProps = new ArrayList<>();
for (Class<?> objectClass : classList) {
annoProps.addAll(ObjectAttributeDescriptor.extractAnnotations(source, objectClass, filter));
}
Collections.sort(annoProps, ATTRIBUTE_DESCRIPTOR_COMPARATOR);
return annoProps;
}
static void extractAnnotations(DBPPropertySource source, ObjectPropertyGroupDescriptor parent, Class<?> theClass, List<ObjectPropertyDescriptor> annoProps, IPropertyFilter filter)
{
Method[] methods = theClass.getMethods();
Map<String, Method> passedNames = new HashMap<>();
for (Method method : methods) {
String methodFullName = method.getDeclaringClass().getName() + "." + method.getName();
final Method prevMethod = passedNames.get(methodFullName);
if (prevMethod != null) {
// The same method but probably with another return type
final Class<?> prevReturnType = prevMethod.getReturnType();
final Class<?> newReturnType = method.getReturnType();
if (newReturnType == null || prevReturnType == null || newReturnType == prevReturnType || !prevReturnType.isAssignableFrom(newReturnType)) {
continue;
}
// Let it another chance. New return types seems to be subclass of previous
}
final PropertyGroup propGroupInfo = method.getAnnotation(PropertyGroup.class);
if (propGroupInfo != null && method.getReturnType() != null) {
// Property group
ObjectPropertyGroupDescriptor groupDescriptor = new ObjectPropertyGroupDescriptor(source, parent, method, propGroupInfo, filter);
annoProps.addAll(groupDescriptor.getChildren());
} else {
final Property propInfo = method.getAnnotation(Property.class);
if (propInfo == null || !BeanUtils.isGetterName(method.getName()) || method.getReturnType() == null) {
continue;
}
// Single property
ObjectPropertyDescriptor desc = new ObjectPropertyDescriptor(source, parent, propInfo, method);
if (filter != null && !filter.select(desc)) {
continue;
}
if (prevMethod != null) {
// Remove previous anno
for (Iterator<ObjectPropertyDescriptor> iter = annoProps.iterator(); iter.hasNext(); ) {
if (iter.next().getId().equals(desc.getId())) {
iter.remove();
}
}
}
annoProps.add(desc);
passedNames.put(methodFullName, method);
}
}
Collections.sort(annoProps, ATTRIBUTE_DESCRIPTOR_COMPARATOR);
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.meta.PropertyGroup;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* ObjectPropertyDescriptor
*/
public class ObjectPropertyGroupDescriptor extends ObjectAttributeDescriptor
{
private PropertyGroup groupInfo;
private List<ObjectPropertyDescriptor> children = new ArrayList<ObjectPropertyDescriptor>();
public ObjectPropertyGroupDescriptor(
DBPPropertySource source,
ObjectPropertyGroupDescriptor parent,
Method getter,
PropertyGroup groupInfo,
IPropertyFilter filter)
{
super(source, parent, getter, groupInfo.id(), groupInfo.order());
this.groupInfo = groupInfo;
extractAnnotations(source, this, getGetter().getReturnType(), children, filter);
}
@Override
public String getCategory()
{
return groupInfo.category();
}
@Override
public String getDescription()
{
return groupInfo.description();
}
public Collection<ObjectPropertyDescriptor> getChildren()
{
return children;
}
public Object getGroupObject(Object object, DBRProgressMonitor progressMonitor)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
if (getParent() != null) {
object = getParent().getGroupObject(object, progressMonitor);
}
if (isLazy(object, false)) {
if (progressMonitor == null) {
throw new IllegalAccessException("Can't read lazy properties with null progress monitor");
}
}
if (isLazy()) {
return getGetter().invoke(object, progressMonitor);
} else {
return getGetter().invoke(object);
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.properties;
import org.jkiss.dbeaver.model.meta.PropertyGroup;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* ObjectPropertyDescriptor
*/
public class ObjectPropertyGroupDescriptor extends ObjectAttributeDescriptor
{
private PropertyGroup groupInfo;
private List<ObjectPropertyDescriptor> children = new ArrayList<ObjectPropertyDescriptor>();
public ObjectPropertyGroupDescriptor(
DBPPropertySource source,
ObjectPropertyGroupDescriptor parent,
Method getter,
PropertyGroup groupInfo,
IPropertyFilter filter)
{
super(source, parent, getter, groupInfo.id(), groupInfo.order());
this.groupInfo = groupInfo;
extractAnnotations(source, this, getGetter().getReturnType(), children, filter);
}
@Override
public String getCategory()
{
return groupInfo.category();
}
@Override
public String getDescription()
{
return groupInfo.description();
}
public Collection<ObjectPropertyDescriptor> getChildren()
{
return children;
}
public Object getGroupObject(Object object, DBRProgressMonitor progressMonitor)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
if (getParent() != null) {
object = getParent().getGroupObject(object, progressMonitor);
}
if (isLazy(object, false)) {
if (progressMonitor == null) {
throw new IllegalAccessException("Can't read lazy properties with null progress monitor");
}
}
if (isLazy()) {
return getGetter().invoke(object, progressMonitor);
} else {
return getGetter().invoke(object);
}
}
}
......@@ -74,6 +74,7 @@ import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
import org.jkiss.dbeaver.model.runtime.*;
import org.jkiss.dbeaver.runtime.DummyRunnableContext;
import org.jkiss.dbeaver.runtime.RunnableContextDelegate;
import org.jkiss.dbeaver.runtime.properties.ObjectPropertyDescriptor;
import org.jkiss.dbeaver.runtime.ui.DBUserInterface;
import org.jkiss.dbeaver.ui.controls.*;
import org.jkiss.dbeaver.utils.GeneralUtils;
......@@ -1295,7 +1296,7 @@ public class UIUtils {
}
Class<?> propertyType = property.getDataType();
if (propertyType == null || CharSequence.class.isAssignableFrom(propertyType)) {
if (false/*property instanceof ObjPropDe property.isMultiLine()*/) {
if (property instanceof ObjectPropertyDescriptor && ((ObjectPropertyDescriptor) property).isMultiLine()) {
return new AdvancedTextCellEditor(parent);
} else {
return new CustomTextCellEditor(parent);
......
......@@ -75,15 +75,9 @@ public class AdvancedTextCellEditor extends DialogCellEditor {
}
protected Button createButton(Composite parent) {
Button result = new Button(parent, SWT.DOWN);
Button result = new Button(parent, SWT.DOWN | SWT.NO_FOCUS);
//result.setText("..."); //$NON-NLS-1$
result.setImage(DBeaverIcons.getImage(UIIcon.DOTS_BUTTON)); //$NON-NLS-1$
result.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
super.focusGained(e);
}
});
return result;
}
......@@ -92,13 +86,22 @@ public class AdvancedTextCellEditor extends DialogCellEditor {
textEditor = new Text(cell, SWT.LEFT);
textEditor.setFont(cell.getFont());
textEditor.setBackground(cell.getBackground());
textEditor.addTraverseListener(e -> {
if (e.detail == SWT.TRAVERSE_RETURN) {
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
String newValue = textEditor.getText();
doSetValue(newValue);
focusLost();
}
});
textFocusListener = new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
String newValue = textEditor.getText();
doSetValue(newValue);
UIUtils.asyncExec(() -> {
if (!UIUtils.hasFocus(cell)) {
doSetValue(newValue);
AdvancedTextCellEditor.this.focusLost();
}
});
......@@ -116,13 +119,14 @@ public class AdvancedTextCellEditor extends DialogCellEditor {
}
if (value != null) {
textEditor.setText((String)value);
textEditor.selectAll();
}
}
@Override
protected Object openDialogBox(Control cellEditorWindow) {
textEditor.removeFocusListener(textFocusListener);
String value = EditTextDialog.editText(cellEditorWindow.getShell(), "Edit text", (String) getValue());
String value = EditTextDialog.editText(cellEditorWindow.getShell(), "Edit value", (String) getValue());
textEditor.addFocusListener(textFocusListener);
return value;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册