Java tutorial
/* Copyright (c) 2013 Richard G. Todd. * Licensed under the terms of the GNU General Public License (GPL) Version 3.0. */ package com.richtodd.android.quiltdesign.app; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.security.InvalidParameterException; import java.util.Date; import org.json.JSONObject; import android.app.ActionBar; import android.app.Activity; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentManager; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.NavUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ImageView; import com.richtodd.android.pdf.DocumentInformation; import com.richtodd.android.pdf.DocumentWriter; import com.richtodd.android.pdf.Rectangle; import com.richtodd.android.quiltdesign.block.BlockContainer; import com.richtodd.android.quiltdesign.block.JSONRepository; import com.richtodd.android.quiltdesign.block.PaperPiecedBlock; import com.richtodd.android.quiltdesign.block.PaperPiecedBlockDocumentFormatter; import com.richtodd.android.quiltdesign.block.PaperPiecedBlockPiece; import com.richtodd.android.quiltdesign.block.RenderFormats; import com.richtodd.android.quiltdesign.block.RenderOptions; import com.richtodd.android.quiltdesign.block.RenderStyles; import com.richtodd.android.quiltdesign.block.Repository; import com.richtodd.android.quiltdesign.block.Swatch; import com.richtodd.android.quiltdesign.block.Theme; import com.richtodd.android.quiltdesign.block.ThemeContainer; import com.richtodd.android.quiltdesign.block.ThemeView; import com.richtodd.android.repository.JSONUtility; import com.richtodd.android.repository.RepositoryException; public class BlockEditActivity extends Activity implements ColorPickerDialogFragment.ColorPickerDialogListener, ThemePickerDialogFragment.ThemePickerDialogListener, BlockEditFragment.BlockEditListener, AlertDialogFragment.AlertDialogListener, EditNameDialogFragment.EditNameDialogListener, ShareOptionsDialogFragment.ShareOptionsDialogListener, BlockOptionsDialogFragment.BlockOptionsDialogListener { // private static final String TAG = "BlockEditActivity"; // // Fields // public static final String ARG_BLOCK_NAME = "com.richtodd.android.quiltdesign.app.BlockEditActivity.blockName"; private static final String KEY_CONFIRM_DELETE = "confirmDelete"; private static final String KEY_FILE_EXISTS = "fileExists"; private String m_blockNameArgument; private Theme m_theme; private ThemeView m_themeView; private Button m_button_setColor; private Button m_button_addPiece; private Button m_button_deletePiece; private String m_saveAsBlockName; // // Overrides // @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_block_edit); getActionBar().setDisplayHomeAsUpEnabled(true); m_blockNameArgument = getIntent().getStringExtra(ARG_BLOCK_NAME); if (savedInstanceState != null) { m_saveAsBlockName = savedInstanceState.getString("saveAsBlockName"); m_theme = (Theme) savedInstanceState.getParcelable("theme"); } ActionBar ab = getActionBar(); ab.setTitle("Edit Block"); ab.setSubtitle(getCurrentBlockName()); FragmentManager fm = getFragmentManager(); // Create color settings fragment. { Fragment f = fm.findFragmentById(R.id.layout_blockEditFragment); if (f == null) { f = BlockEditFragment.create(m_blockNameArgument); fm.beginTransaction().add(R.id.layout_blockEditFragment, f).commit(); } } m_themeView = (ThemeView) findViewById(R.id.themeView); m_themeView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Swatch swatch = (Swatch) m_themeView.getItemAtPosition(position); BlockEditFragment fragment = getBlockEditFragment(); if (fragment != null) { fragment.setColor(swatch.getColor()); } } }); m_themeView.setTheme(m_theme); m_button_setColor = (Button) findViewById(R.id.button_setColor); m_button_setColor.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chooseColor(); } }); m_button_addPiece = (Button) findViewById(R.id.button_addPiece); m_button_addPiece.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { BlockEditFragment fragment = getBlockEditFragment(); int color = fragment.getColor(); PaperPiecedBlockPiece piece = fragment.addPiece(color); onPieceSelected(fragment, piece); } }); m_button_deletePiece = (Button) findViewById(R.id.button_deletePiece); m_button_deletePiece.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { BlockEditFragment fragment = getBlockEditFragment(); fragment.deletePiece(); onPieceSelected(fragment, null); } }); ImageView button_refreshTheme = (ImageView) findViewById(R.id.button_refreshTheme); button_refreshTheme.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { refreshTheme(); } }); ImageView button_selectTheme = (ImageView) findViewById(R.id.button_selectTheme); button_selectTheme.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chooseTheme(); } }); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("saveAsBlockName", m_saveAsBlockName); outState.putParcelable("theme", m_theme); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options_activity_block_edit, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); switch (itemId) { case android.R.id.home: { NavUtils.navigateUpFromSameTask(this); return true; } case R.id.menu_blockOptions: { PaperPiecedBlock block = getBlockEditFragment().getBlock(); BlockOptionsDialogFragment dialog = BlockOptionsDialogFragment.create((int) block.getWidth()); dialog.show(getFragmentManager(), null); return true; } case R.id.menu_shareBlock: { ShareOptionsDialogFragment dialog = ShareOptionsDialogFragment.create(Intent.ACTION_SEND); dialog.show(getFragmentManager(), null); return true; } case R.id.menu_viewBlock: { ShareOptionsDialogFragment dialog = ShareOptionsDialogFragment.create(Intent.ACTION_VIEW); dialog.show(getFragmentManager(), null); return true; } case R.id.menu_renameBlock: { showEditNameDialog(); return true; } case R.id.menu_deleteBlock: { AlertDialogFragment dialog = AlertDialogFragment.create(KEY_CONFIRM_DELETE, getString(R.string.alert_message_confirmBlockDelete), getString(R.string.alert_button_yes), getString(R.string.alert_button_no)); dialog.show(getFragmentManager(), null); return true; } case R.id.menu_cancelChanges: { getBlockEditFragment().setSaveSuppressed(true); finish(); return true; } case R.id.menu_settings: { Intent intent = new Intent(this, BlockPreferenceActivity.class); startActivity(intent); return true; } } return super.onOptionsItemSelected(item); } private void refreshTheme() { m_theme = getBlockEditFragment().getBlock() .createTheme(getResources().getInteger(R.integer.theme_swatch_count)); m_themeView.setTheme(m_theme); } // // Overrides - Listeners // @Override public void onBlockLoaded(BlockEditFragment fragment, PaperPiecedBlock block) { if (m_theme == null) { if (block.getPieces().size() == 0 && block.getBackgroundColor() == 0) { m_theme = Theme.createColors(getResources().getInteger(R.integer.theme_swatch_count), 0.8f, 1f); fragment.setColor(m_theme.getSwatches().get(0).getColor()); fragment.addPiece(m_theme.getSwatches().get(1).getColor()); block.clearDirty(); } else { m_theme = block.createTheme(getResources().getInteger(R.integer.theme_swatch_count)); } if (m_themeView != null) { m_themeView.setTheme(m_theme); } } } @Override public void onPieceSelected(BlockEditFragment fragment, PaperPiecedBlockPiece piece) { enableDisableButtons(); } @Override public void onColorPickerPositiveClick(DialogFragment dialog, int color) { BlockEditFragment fragment = getBlockEditFragment(); if (fragment != null) { fragment.setColor(color); } } @Override public void onColorPickerNegativeClick(DialogFragment dialog) { // No action required. } @Override public void onThemePickerPositiveClick(DialogFragment dialog, String themeName) throws Exception { if (themeName != null) { Repository repository = Repository.getDefaultRepository(this); ThemeContainer themes = repository.getThemes(); m_theme = themes.loadTheme(themeName); m_themeView.setTheme(m_theme); } } @Override public void onThemePickerNegativeClick(DialogFragment dialog) { // No action required. } @Override public void onAlertDialogPositiveClick(DialogFragment dialog, String key) throws Exception { if (key.equals(KEY_CONFIRM_DELETE)) { getBlockEditFragment().setSaveSuppressed(true); Repository repository = Repository.getDefaultRepository(this); BlockContainer blocks = repository.getBlocks(); blocks.deleteBlock(m_blockNameArgument); finish(); } else if (key.equals(KEY_FILE_EXISTS)) { showEditNameDialog(); } else { throw new InvalidParameterException("Unknown key " + key); } } @Override public void onAlertDialogNegativeClick(DialogFragment dialog, String key) { // No action required. } @Override public void onEditNamePositiveClick(DialogFragment dialog, String name) throws Exception { Repository repository = Repository.getDefaultRepository(this); BlockContainer blocks = repository.getBlocks(); if (blocks.blockExists(name)) { AlertDialogFragment alertDialog = AlertDialogFragment.create(KEY_FILE_EXISTS, getString(R.string.alert_message_blockAlreadyExists), getString(R.string.alert_button_acknowledge), null); alertDialog.show(getFragmentManager(), null); } else { m_saveAsBlockName = name; getBlockEditFragment().setSaveAsBlockName(m_saveAsBlockName); } ActionBar ab = getActionBar(); ab.setSubtitle(getCurrentBlockName()); } @Override public void onEditNameNegativeClick(DialogFragment dialog) { // No action required. } @Override public void onShareOptionsPositiveClick(DialogFragment dialog, RenderStyles renderStyle, RenderFormats renderFormat, String intentAction) throws Exception { Uri uriFile; String type; switch (renderFormat) { case Bitmap: uriFile = saveBitmap(renderStyle); type = "image/png"; break; case PDF: uriFile = savePDF(renderStyle); type = "application/pdf"; break; case QuiltDesign: uriFile = saveQuiltDesign(); type = "application/vnd.richtodd.quiltdesign"; break; default: throw new IllegalArgumentException("Unknown render format " + renderFormat); } Intent intent = new Intent(intentAction); if (intentAction.equals(Intent.ACTION_SEND)) { intent.putExtra(Intent.EXTRA_STREAM, uriFile); intent.setType(type); startActivity(Intent.createChooser(intent, "Share With")); } else { intent.setDataAndType(uriFile, type); startActivity(Intent.createChooser(intent, "View With")); } } @Override public void onShareOptionsNegativeClick(DialogFragment dialog) { // No action required. } @Override public void onBlockOptionsPositiveClick(DialogFragment dialog, int size) { BlockEditFragment fragment = getBlockEditFragment(); fragment.setSize(size); } @Override public void onBlockOptionsNegativeClick(DialogFragment dialog) { // No action required. } // // Private // private String getCurrentBlockName() { if (m_saveAsBlockName != null) { return m_saveAsBlockName; } else { return m_blockNameArgument; } } private Uri saveBitmap(RenderStyles renderStyle) throws IOException { BlockEditFragment fragment = getBlockEditFragment(); PaperPiecedBlock block = fragment.getBlock(); File file = new File(StorageUtility.getPublicFolder(), getCurrentBlockName() + ".png"); saveBitmap(block, file, renderStyle); Uri uri = Uri.fromFile(file); return uri; } private void saveBitmap(PaperPiecedBlock block, File file, RenderStyles renderStyle) throws IOException { int marginSize = getResources().getInteger(R.integer.block_margin_size); int shareDensity = Preferences.getEffectiveShareDensity(this, PreferenceManager.getDefaultSharedPreferences(this)); float width = block.getWidth(); float height = block.getHeight(); RenderOptions renderOptions = new RenderOptions(); renderOptions.setWidth((int) (shareDensity * width)); renderOptions.setHeight((int) (shareDensity * height)); renderOptions.setLeft(marginSize); renderOptions.setTop(marginSize); renderOptions.setStrokeWidth(2); renderOptions.setRenderStyle(renderStyle); Bitmap bitmap = renderOptions.createBitmap(); block.draw(bitmap, renderOptions); FileOutputStream stream = new FileOutputStream(file); try { bitmap.compress(CompressFormat.JPEG, 100, stream); } finally { stream.close(); } } private Uri savePDF(RenderStyles renderStyle) throws IOException { BlockEditFragment fragment = getBlockEditFragment(); PaperPiecedBlock block = fragment.getBlock(); File file = new File(StorageUtility.getPublicFolder(), getCurrentBlockName() + ".pdf"); savePDF(block, file, renderStyle, getCurrentBlockName()); Uri uri = Uri.fromFile(file); return uri; } private void savePDF(PaperPiecedBlock block, File file, RenderStyles renderStyle, String title) throws IOException { DocumentWriter writer = new DocumentWriter(new BufferedOutputStream(new FileOutputStream(file))); try { writer.beginDocument(Rectangle.getLetterPageBoundary(), Rectangle.getLetterContentBoundary()); writer.beginPage(); PaperPiecedBlockDocumentFormatter formatter = new PaperPiecedBlockDocumentFormatter(); formatter.formatBlock(block, title, writer, renderStyle, false); writer.endPage(); DocumentInformation documentInformation = new DocumentInformation(); documentInformation.setTitle(title); documentInformation.setCreationDate(new Date()); writer.endDocument(documentInformation); } finally { writer.close(); } } private Uri saveQuiltDesign() throws IOException, RepositoryException { BlockEditFragment fragment = getBlockEditFragment(); PaperPiecedBlock block = fragment.getBlock(); File file = new File(StorageUtility.getPublicFolder(), getCurrentBlockName() + ".quiltdesign"); saveQuiltDesign(block, file); Uri uri = Uri.fromFile(file); return uri; } private void saveQuiltDesign(PaperPiecedBlock block, File file) throws RepositoryException { JSONObject jsonRepository = new JSONObject(); JSONRepository repository = new JSONRepository(jsonRepository, null); repository.getBlocks().savePaperPiecedBlock(getCurrentBlockName(), block, null); JSONUtility.saveJSONObject(file, jsonRepository); } private void showEditNameDialog() { String blockName = getCurrentBlockName(); EditNameDialogFragment dialog = EditNameDialogFragment.create("Block", blockName); dialog.show(getFragmentManager(), null); } private void chooseColor() { BlockEditFragment fragment = getBlockEditFragment(); int color = fragment.getColor(); ColorPickerDialogFragment dialog = ColorPickerDialogFragment.create(color); dialog.show(getFragmentManager(), "ColorPickerDialogFragment"); } private void chooseTheme() { ThemePickerDialogFragment dialog = ThemePickerDialogFragment.create(); dialog.show(getFragmentManager(), "ThemePickerDialogFragment"); } private void enableDisableButtons() { BlockEditFragment fragment = getBlockEditFragment(); m_button_addPiece.setEnabled(fragment.canAddPiece()); m_button_deletePiece.setEnabled(fragment.canDeletePiece()); } private BlockEditFragment getBlockEditFragment() { return (BlockEditFragment) getFragmentManager().findFragmentById(R.id.layout_blockEditFragment); } }