avm2: Implement TextField.maxChars

This commit is contained in:
Adrian Wielgosik 2023-01-18 21:50:14 +01:00 committed by Adrian Wielgosik
parent f83c573734
commit fb4d2d3f04
2 changed files with 73 additions and 12 deletions

View File

@ -1241,6 +1241,41 @@ pub fn set_scroll_h<'gc>(
Ok(Value::Undefined)
}
pub fn max_chars<'gc>(
_activation: &mut Activation<'_, 'gc>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(this) = this
.and_then(|this| this.as_display_object())
.and_then(|this| this.as_edit_text())
{
return Ok(this.max_chars().into());
}
Ok(Value::Undefined)
}
pub fn set_max_chars<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(this) = this
.and_then(|this| this.as_display_object())
.and_then(|this| this.as_edit_text())
{
let input = args
.get(0)
.cloned()
.unwrap_or(Value::Undefined)
.coerce_to_i32(activation)?;
this.set_max_chars(input, &mut activation.context);
}
Ok(Value::Undefined)
}
/// Construct `TextField`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
let class = Class::new(
@ -1288,6 +1323,7 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
("length", Some(length), None),
("maxScrollH", Some(max_scroll_h), None),
("maxScrollV", Some(max_scroll_v), None),
("maxChars", Some(max_chars), Some(set_max_chars)),
("multiline", Some(multiline), Some(set_multiline)),
("scrollH", Some(scroll_h), Some(set_scroll_h)),
("scrollV", Some(scroll_v), Some(set_scroll_v)),

View File

@ -133,6 +133,10 @@ pub struct EditTextData<'gc> {
/// How many lines down the text is offset by. 1-based index.
scroll: usize,
/// The limit of characters that can be manually input by the user.
/// Doesn't affect script-triggered modifications.
max_chars: i32,
/// Flags indicating the text field's settings.
flags: EditTextFlag,
}
@ -278,6 +282,7 @@ impl<'gc> EditText<'gc> {
hscroll: 0.0,
line_data,
scroll: 1,
max_chars: 0,
},
));
@ -1122,6 +1127,14 @@ impl<'gc> EditText<'gc> {
self.0.write(context.gc_context).scroll = clamped;
}
pub fn max_chars(self) -> i32 {
self.0.read().max_chars
}
pub fn set_max_chars(self, value: i32, context: &mut UpdateContext<'_, 'gc>) {
self.0.write(context.gc_context).max_chars = value;
}
pub fn screen_position_to_index(self, position: (Twips, Twips)) -> Option<usize> {
let text = self.0.read();
let position = self.global_to_local(position);
@ -1212,6 +1225,17 @@ impl<'gc> EditText<'gc> {
}
}
code if !(code as char).is_control() => {
let can_insert = {
let read = self.0.read();
let max_chars = read.max_chars;
if max_chars == 0 {
true
} else {
let text_len = read.text_spans.text().len();
text_len < max_chars.max(0) as usize
}
};
if can_insert {
self.replace_text(
selection.start(),
selection.end(),
@ -1225,6 +1249,7 @@ impl<'gc> EditText<'gc> {
);
changed = true;
}
}
_ => {}
}