avm1: Add EditText variable property

Add `EditText::variable` as well as `TextField.variable` property.
This commit only adds the getter/setter and does not yet add the
binding functionality.
This commit is contained in:
Mike Welsh 2020-06-09 00:17:30 -07:00
parent dd50071240
commit a922fd559f
2 changed files with 78 additions and 1 deletions

View File

@ -312,6 +312,46 @@ pub fn set_multiline<'gc>(
Ok(Value::Undefined.into())
}
fn variable<'gc>(
_avm: &mut Avm1<'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
if let Some(etext) = this
.as_display_object()
.and_then(|dobj| dobj.as_edit_text())
{
if let Some(variable) = etext.variable() {
return Ok(variable.to_string().into());
}
}
// Unset `variable` retuns null, not undefined
Ok(Value::Null.into())
}
fn set_variable<'gc>(
avm: &mut Avm1<'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error<'gc>> {
let variable = match args.get(0) {
None | Some(Value::Undefined) | Some(Value::Null) => None,
Some(v) => Some(v.coerce_to_string(avm, context)?),
};
if let Some(etext) = this
.as_display_object()
.and_then(|dobj| dobj.as_edit_text())
{
etext.set_variable(variable.map(|v| v.into_owned()), context);
}
Ok(Value::Undefined.into())
}
pub fn word_wrap<'gc>(
_avm: &mut Avm1<'gc>,
_context: &mut UpdateContext<'_, 'gc, '_>,
@ -469,6 +509,13 @@ pub fn attach_virtual_properties<'gc>(gc_context: MutationContext<'gc, '_>, obje
Some(Executable::Native(set_multiline)),
ReadOnly.into(),
);
object.add_property(
gc_context,
"variable",
Executable::Native(variable),
Some(Executable::Native(set_variable)),
DontDelete | ReadOnly | DontEnum,
);
object.add_property(
gc_context,
"wordWrap",

View File

@ -12,7 +12,7 @@ use crate::tag_utils::SwfMovie;
use crate::transform::Transform;
use crate::xml::XMLDocument;
use gc_arena::{Collect, Gc, GcCell, MutationContext};
use std::sync::Arc;
use std::{cell::Ref, sync::Arc};
use swf::Twips;
/// Boxed error type.
@ -99,6 +99,9 @@ pub struct EditTextData<'gc> {
/// The AVM1 object handle
object: Option<Object<'gc>>,
/// The variable path that this text field is bound to (AVM1 only).
variable: Option<String>,
}
impl<'gc> EditText<'gc> {
@ -146,6 +149,12 @@ impl<'gc> EditText<'gc> {
base.matrix_mut(context.gc_context).tx = bounds.x_min;
base.matrix_mut(context.gc_context).ty = bounds.y_min;
let variable = if !swf_tag.variable_name.is_empty() {
Some(swf_tag.variable_name.clone())
} else {
None
};
let et = EditText(GcCell::allocate(
context.gc_context,
EditTextData {
@ -169,6 +178,7 @@ impl<'gc> EditText<'gc> {
intrinsic_bounds,
bounds,
autosize: AutoSizeMode::None,
variable,
},
));
@ -405,6 +415,26 @@ impl<'gc> EditText<'gc> {
base_width
}
/// Returns the variable that this text field is bound to.
pub fn variable(&self) -> Option<Ref<str>> {
let text = self.0.read();
if text.variable.is_some() {
Some(Ref::map(text, |text| text.variable.as_deref().unwrap()))
} else {
None
}
}
pub fn set_variable(self, variable: Option<String>, context: &mut UpdateContext<'_, 'gc, '_>) {
self.0.write(context.gc_context).variable = variable
}
/// Construct a base text transform for this `EditText`, to be used for
/// evaluating fonts.
///
/// The `text_transform` constitutes the base transform that all text is
/// written into.
/// Redraw the border of this `EditText`.
fn redraw_border(self, context: MutationContext<'gc, '_>) {
let mut write = self.0.write(context);